github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/kv/kvserver/raft.go (about) 1 // Copyright 2015 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package kvserver 12 13 import ( 14 "bytes" 15 "context" 16 "fmt" 17 "sync" 18 19 "github.com/cockroachdb/cockroach/pkg/kv/kvserver/kvserverbase" 20 "github.com/cockroachdb/cockroach/pkg/util/log" 21 "go.etcd.io/etcd/raft" 22 "go.etcd.io/etcd/raft/raftpb" 23 ) 24 25 // maxRaftMsgType is the maximum value in the raft.MessageType enum. 26 const maxRaftMsgType = raftpb.MsgPreVoteResp 27 28 func init() { 29 for v := range raftpb.MessageType_name { 30 typ := raftpb.MessageType(v) 31 if typ > maxRaftMsgType { 32 panic(fmt.Sprintf("raft.MessageType (%s) with value larger than maxRaftMsgType", typ)) 33 } 34 } 35 } 36 37 // init installs an adapter to use clog for log messages from raft which 38 // don't belong to any range. 39 func init() { 40 raft.SetLogger(&raftLogger{ctx: context.Background()}) 41 } 42 43 // *clogLogger implements the raft.Logger interface. Note that all methods 44 // must be defined on the pointer type rather than the value type because 45 // (at least in the go 1.4 compiler), methods on a value type called through 46 // an interface pointer go through an additional layer of indirection that 47 // appears on the stack, and would make all our stack frame offsets incorrect. 48 // 49 // Raft is fairly verbose at the "info" level, so we map "info" messages to 50 // clog.V(1) and "debug" messages to clog.V(2). 51 // 52 // This file is named raft.go instead of something like logger.go because this 53 // file's name is used to determine the vmodule parameter: --vmodule=raft=1 54 type raftLogger struct { 55 ctx context.Context 56 } 57 58 func (r *raftLogger) Debug(v ...interface{}) { 59 if log.V(3) { 60 log.InfofDepth(r.ctx, 1, "", v...) 61 } 62 } 63 64 func (r *raftLogger) Debugf(format string, v ...interface{}) { 65 if log.V(3) { 66 log.InfofDepth(r.ctx, 1, format, v...) 67 } 68 } 69 70 func (r *raftLogger) Info(v ...interface{}) { 71 if log.V(2) { 72 log.InfofDepth(r.ctx, 1, "", v...) 73 } 74 } 75 76 func (r *raftLogger) Infof(format string, v ...interface{}) { 77 if log.V(2) { 78 log.InfofDepth(r.ctx, 1, format, v...) 79 } 80 } 81 82 func (r *raftLogger) Warning(v ...interface{}) { 83 log.WarningfDepth(r.ctx, 1, "", v...) 84 } 85 86 func (r *raftLogger) Warningf(format string, v ...interface{}) { 87 log.WarningfDepth(r.ctx, 1, format, v...) 88 } 89 90 func (r *raftLogger) Error(v ...interface{}) { 91 log.ErrorfDepth(r.ctx, 1, "", v...) 92 } 93 94 func (r *raftLogger) Errorf(format string, v ...interface{}) { 95 log.ErrorfDepth(r.ctx, 1, format, v...) 96 } 97 98 func (r *raftLogger) Fatal(v ...interface{}) { 99 wrapNumbersAsSafe(v) 100 log.FatalfDepth(r.ctx, 1, "", v...) 101 } 102 103 func (r *raftLogger) Fatalf(format string, v ...interface{}) { 104 wrapNumbersAsSafe(v) 105 log.FatalfDepth(r.ctx, 1, format, v...) 106 } 107 108 func (r *raftLogger) Panic(v ...interface{}) { 109 wrapNumbersAsSafe(v) 110 log.FatalfDepth(r.ctx, 1, "", v...) 111 } 112 113 func (r *raftLogger) Panicf(format string, v ...interface{}) { 114 wrapNumbersAsSafe(v) 115 log.FatalfDepth(r.ctx, 1, format, v...) 116 } 117 118 func wrapNumbersAsSafe(v ...interface{}) { 119 for i := range v { 120 switch v[i].(type) { 121 case uint: 122 v[i] = log.Safe(v[i]) 123 case uint8: 124 v[i] = log.Safe(v[i]) 125 case uint16: 126 v[i] = log.Safe(v[i]) 127 case uint32: 128 v[i] = log.Safe(v[i]) 129 case uint64: 130 v[i] = log.Safe(v[i]) 131 case int: 132 v[i] = log.Safe(v[i]) 133 case int8: 134 v[i] = log.Safe(v[i]) 135 case int16: 136 v[i] = log.Safe(v[i]) 137 case int32: 138 v[i] = log.Safe(v[i]) 139 case int64: 140 v[i] = log.Safe(v[i]) 141 case float32: 142 v[i] = log.Safe(v[i]) 143 case float64: 144 v[i] = log.Safe(v[i]) 145 default: 146 } 147 } 148 } 149 150 func verboseRaftLoggingEnabled() bool { 151 return log.V(5) 152 } 153 154 func logRaftReady(ctx context.Context, ready raft.Ready) { 155 if !verboseRaftLoggingEnabled() { 156 return 157 } 158 159 var buf bytes.Buffer 160 if ready.SoftState != nil { 161 fmt.Fprintf(&buf, " SoftState updated: %+v\n", *ready.SoftState) 162 } 163 if !raft.IsEmptyHardState(ready.HardState) { 164 fmt.Fprintf(&buf, " HardState updated: %+v\n", ready.HardState) 165 } 166 for i, e := range ready.Entries { 167 fmt.Fprintf(&buf, " New Entry[%d]: %.200s\n", 168 i, raft.DescribeEntry(e, raftEntryFormatter)) 169 } 170 for i, e := range ready.CommittedEntries { 171 fmt.Fprintf(&buf, " Committed Entry[%d]: %.200s\n", 172 i, raft.DescribeEntry(e, raftEntryFormatter)) 173 } 174 if !raft.IsEmptySnap(ready.Snapshot) { 175 snap := ready.Snapshot 176 snap.Data = nil 177 fmt.Fprintf(&buf, " Snapshot updated: %v\n", snap) 178 } 179 for i, m := range ready.Messages { 180 fmt.Fprintf(&buf, " Outgoing Message[%d]: %.200s\n", 181 i, raftDescribeMessage(m, raftEntryFormatter)) 182 } 183 log.Infof(ctx, "raft ready (must-sync=%t)\n%s", ready.MustSync, buf.String()) 184 } 185 186 // This is a fork of raft.DescribeMessage with a tweak to avoid logging 187 // snapshot data. 188 func raftDescribeMessage(m raftpb.Message, f raft.EntryFormatter) string { 189 var buf bytes.Buffer 190 fmt.Fprintf(&buf, "%x->%x %v Term:%d Log:%d/%d", m.From, m.To, m.Type, m.Term, m.LogTerm, m.Index) 191 if m.Reject { 192 fmt.Fprintf(&buf, " Rejected (Hint: %d)", m.RejectHint) 193 } 194 if m.Commit != 0 { 195 fmt.Fprintf(&buf, " Commit:%d", m.Commit) 196 } 197 if len(m.Entries) > 0 { 198 fmt.Fprintf(&buf, " Entries:[") 199 for i, e := range m.Entries { 200 if i != 0 { 201 buf.WriteString(", ") 202 } 203 buf.WriteString(raft.DescribeEntry(e, f)) 204 } 205 fmt.Fprintf(&buf, "]") 206 } 207 if !raft.IsEmptySnap(m.Snapshot) { 208 snap := m.Snapshot 209 snap.Data = nil 210 fmt.Fprintf(&buf, " Snapshot:%v", snap) 211 } 212 return buf.String() 213 } 214 215 func raftEntryFormatter(data []byte) string { 216 if len(data) == 0 { 217 return "[empty]" 218 } 219 commandID, _ := DecodeRaftCommand(data) 220 return fmt.Sprintf("[%x] [%d]", commandID, len(data)) 221 } 222 223 var raftMessageRequestPool = sync.Pool{ 224 New: func() interface{} { 225 return &RaftMessageRequest{} 226 }, 227 } 228 229 func newRaftMessageRequest() *RaftMessageRequest { 230 return raftMessageRequestPool.Get().(*RaftMessageRequest) 231 } 232 233 func (m *RaftMessageRequest) release() { 234 *m = RaftMessageRequest{} 235 raftMessageRequestPool.Put(m) 236 } 237 238 // IsPreemptive returns whether this is a preemptive snapshot or a Raft 239 // snapshot. 240 func (h *SnapshotRequest_Header) IsPreemptive() bool { 241 // Preemptive snapshots are addressed to replica ID 0. No other requests to 242 // replica ID 0 are allowed. 243 return h.RaftMessageRequest.ToReplica.ReplicaID == 0 244 } 245 246 // traceEntries records the provided event for all proposals corresponding 247 // to the entries contained in ents. The vmodule level for raft must be at 248 // least 1. 249 func (r *Replica) traceEntries(ents []raftpb.Entry, event string) { 250 if log.V(1) || r.store.TestingKnobs().TraceAllRaftEvents { 251 ids := extractIDs(nil, ents) 252 traceProposals(r, ids, event) 253 } 254 } 255 256 // traceMessageSends records the provided event for all proposals contained in 257 // in entries contained in msgs. The vmodule level for raft must be at 258 // least 1. 259 func (r *Replica) traceMessageSends(msgs []raftpb.Message, event string) { 260 if log.V(1) || r.store.TestingKnobs().TraceAllRaftEvents { 261 var ids []kvserverbase.CmdIDKey 262 for _, m := range msgs { 263 ids = extractIDs(ids, m.Entries) 264 } 265 traceProposals(r, ids, event) 266 } 267 } 268 269 // extractIDs decodes and appends each of the ids corresponding to the entries 270 // in ents to ids and returns the result. 271 func extractIDs(ids []kvserverbase.CmdIDKey, ents []raftpb.Entry) []kvserverbase.CmdIDKey { 272 for _, e := range ents { 273 if e.Type == raftpb.EntryNormal && len(e.Data) > 0 { 274 id, _ := DecodeRaftCommand(e.Data) 275 ids = append(ids, id) 276 } 277 } 278 return ids 279 } 280 281 // traceLocalProposals logs a trace event with the provided string for each 282 // locally proposed command which corresponds to an id in ids. 283 func traceProposals(r *Replica, ids []kvserverbase.CmdIDKey, event string) { 284 ctxs := make([]context.Context, 0, len(ids)) 285 r.mu.RLock() 286 for _, id := range ids { 287 if prop, ok := r.mu.proposals[id]; ok { 288 ctxs = append(ctxs, prop.ctx) 289 } 290 } 291 r.mu.RUnlock() 292 for _, ctx := range ctxs { 293 log.Eventf(ctx, "%v", event) 294 } 295 }