github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/event.go (about) 1 // Copyright 2021 The Bitalosdb author(hustxrb@163.com) and other contributors. 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 bitalosdb 16 17 import ( 18 "time" 19 20 "github.com/zuoyebang/bitalosdb/internal/humanize" 21 22 "github.com/cockroachdb/redact" 23 ) 24 25 type DiskSlowInfo struct { 26 Path string 27 Duration time.Duration 28 } 29 30 func (i DiskSlowInfo) String() string { 31 return redact.StringWithoutMarkers(i) 32 } 33 34 func (i DiskSlowInfo) SafeFormat(w redact.SafePrinter, _ rune) { 35 w.Printf("disk slowness detected: write to file %s has been ongoing for %0.1fs", 36 i.Path, redact.Safe(i.Duration.Seconds())) 37 } 38 39 type FlushInfo struct { 40 Index int 41 Reason string 42 Input int 43 Iterated uint64 44 Written int64 45 keyWritten int64 46 keyPrefixDeleteKind int64 47 prefixDeleteNum int64 48 Duration time.Duration 49 Done bool 50 Err error 51 } 52 53 func (i FlushInfo) String() string { 54 return redact.StringWithoutMarkers(i) 55 } 56 57 func (i FlushInfo) SafeFormat(w redact.SafePrinter, _ rune) { 58 if i.Err != nil { 59 w.Printf("[BITOWER %d] flush error: %s", i.Index, i.Err) 60 return 61 } 62 63 if !i.Done { 64 w.Printf("[BITOWER %d] flushing %d memtable to bitforest", i.Index, i.Input) 65 return 66 } 67 68 w.Printf("[BITOWER %d] flushed %d memtable to bitforest iterated(%s) written(%s) keys(%d) keysPdKind(%d) pdNum(%d), in %.3fs, output rate %s/s", 69 i.Index, 70 i.Input, 71 humanize.Uint64(i.Iterated), 72 humanize.Int64(i.Written), 73 i.keyWritten, 74 i.keyPrefixDeleteKind, 75 i.prefixDeleteNum, 76 i.Duration.Seconds(), 77 humanize.Uint64(uint64(float64(i.Written)/i.Duration.Seconds()))) 78 } 79 80 type WALCreateInfo struct { 81 Index int 82 Path string 83 FileNum FileNum 84 RecycledFileNum FileNum 85 Err error 86 } 87 88 func (i WALCreateInfo) String() string { 89 return redact.StringWithoutMarkers(i) 90 } 91 92 func (i WALCreateInfo) SafeFormat(w redact.SafePrinter, _ rune) { 93 if i.Err != nil { 94 w.Printf("[BITOWER %d] WAL create error: %s", redact.Safe(i.Index), i.Err) 95 return 96 } 97 98 if i.RecycledFileNum == 0 { 99 w.Printf("[BITOWER %d] WAL created %s", redact.Safe(i.Index), redact.Safe(i.FileNum)) 100 return 101 } 102 103 w.Printf("[BITOWER %d] WAL created %s (recycled %s)", 104 redact.Safe(i.Index), redact.Safe(i.FileNum), redact.Safe(i.RecycledFileNum)) 105 } 106 107 type WALDeleteInfo struct { 108 Index int 109 Path string 110 FileNum FileNum 111 Err error 112 } 113 114 func (i WALDeleteInfo) String() string { 115 return redact.StringWithoutMarkers(i) 116 } 117 118 func (i WALDeleteInfo) SafeFormat(w redact.SafePrinter, _ rune) { 119 if i.Err != nil { 120 w.Printf("[BITOWER %d] WAL delete error: %s", redact.Safe(i.Index), i.Err) 121 return 122 } 123 w.Printf("[BITOWER %d] WAL deleted %s", redact.Safe(i.Index), redact.Safe(i.FileNum)) 124 } 125 126 type WriteStallBeginInfo struct { 127 Index int 128 Reason string 129 } 130 131 func (i WriteStallBeginInfo) String() string { 132 return redact.StringWithoutMarkers(i) 133 } 134 135 func (i WriteStallBeginInfo) SafeFormat(w redact.SafePrinter, _ rune) { 136 w.Printf("[BITOWER %d] write stall beginning: %s", redact.Safe(i.Index), redact.Safe(i.Reason)) 137 } 138 139 type EventListener struct { 140 BackgroundError func(error) 141 DiskSlow func(DiskSlowInfo) 142 FlushBegin func(FlushInfo) 143 FlushEnd func(FlushInfo) 144 WALCreated func(WALCreateInfo) 145 WALDeleted func(WALDeleteInfo) 146 WriteStallBegin func(WriteStallBeginInfo) 147 WriteStallEnd func() 148 } 149 150 func (l *EventListener) EnsureDefaults(logger Logger) { 151 if l.BackgroundError == nil { 152 if logger != nil { 153 l.BackgroundError = func(err error) { 154 logger.Errorf("background error: %s", err) 155 } 156 } else { 157 l.BackgroundError = func(error) {} 158 } 159 } 160 if l.DiskSlow == nil { 161 l.DiskSlow = func(info DiskSlowInfo) {} 162 } 163 if l.FlushBegin == nil { 164 l.FlushBegin = func(info FlushInfo) {} 165 } 166 if l.FlushEnd == nil { 167 l.FlushEnd = func(info FlushInfo) {} 168 } 169 if l.WALCreated == nil { 170 l.WALCreated = func(info WALCreateInfo) {} 171 } 172 if l.WALDeleted == nil { 173 l.WALDeleted = func(info WALDeleteInfo) {} 174 } 175 if l.WriteStallBegin == nil { 176 l.WriteStallBegin = func(info WriteStallBeginInfo) {} 177 } 178 if l.WriteStallEnd == nil { 179 l.WriteStallEnd = func() {} 180 } 181 } 182 183 func MakeLoggingEventListener(logger Logger) EventListener { 184 if logger == nil { 185 logger = DefaultLogger 186 } 187 188 return EventListener{ 189 BackgroundError: func(err error) { 190 logger.Infof("background error: %s", err) 191 }, 192 DiskSlow: func(info DiskSlowInfo) { 193 logger.Infof("%s", info) 194 }, 195 FlushBegin: func(info FlushInfo) { 196 logger.Infof("%s", info) 197 }, 198 FlushEnd: func(info FlushInfo) { 199 logger.Infof("%s", info) 200 }, 201 WALCreated: func(info WALCreateInfo) { 202 logger.Infof("%s", info) 203 }, 204 WALDeleted: func(info WALDeleteInfo) { 205 logger.Infof("%s", info) 206 }, 207 WriteStallBegin: func(info WriteStallBeginInfo) { 208 logger.Infof("%s", info) 209 }, 210 WriteStallEnd: func() { 211 logger.Infof("write stall ending") 212 }, 213 } 214 } 215 216 func TeeEventListener(a, b EventListener) EventListener { 217 a.EnsureDefaults(nil) 218 b.EnsureDefaults(nil) 219 return EventListener{ 220 BackgroundError: func(err error) { 221 a.BackgroundError(err) 222 b.BackgroundError(err) 223 }, 224 DiskSlow: func(info DiskSlowInfo) { 225 a.DiskSlow(info) 226 b.DiskSlow(info) 227 }, 228 FlushBegin: func(info FlushInfo) { 229 a.FlushBegin(info) 230 b.FlushBegin(info) 231 }, 232 FlushEnd: func(info FlushInfo) { 233 a.FlushEnd(info) 234 b.FlushEnd(info) 235 }, 236 WALCreated: func(info WALCreateInfo) { 237 a.WALCreated(info) 238 b.WALCreated(info) 239 }, 240 WALDeleted: func(info WALDeleteInfo) { 241 a.WALDeleted(info) 242 b.WALDeleted(info) 243 }, 244 WriteStallBegin: func(info WriteStallBeginInfo) { 245 a.WriteStallBegin(info) 246 b.WriteStallBegin(info) 247 }, 248 WriteStallEnd: func() { 249 a.WriteStallEnd() 250 b.WriteStallEnd() 251 }, 252 } 253 }