github.com/pingcap/br@v5.3.0-alpha.0.20220125034240-ec59c7b6ce30+incompatible/pkg/logutil/logging.go (about) 1 // Copyright 2020 PingCAP, Inc. Licensed under Apache-2.0. 2 3 package logutil 4 5 import ( 6 "encoding/hex" 7 "fmt" 8 "strings" 9 10 "github.com/google/uuid" 11 "github.com/pingcap/errors" 12 backuppb "github.com/pingcap/kvproto/pkg/backup" 13 "github.com/pingcap/kvproto/pkg/import_sstpb" 14 "github.com/pingcap/kvproto/pkg/metapb" 15 "github.com/pingcap/log" 16 "go.uber.org/zap" 17 "go.uber.org/zap/zapcore" 18 19 "github.com/pingcap/br/pkg/redact" 20 ) 21 22 // AbbreviatedArrayMarshaler abbreviates an array of elements. 23 type AbbreviatedArrayMarshaler []string 24 25 // MarshalLogArray implements zapcore.ArrayMarshaler. 26 func (abb AbbreviatedArrayMarshaler) MarshalLogArray(encoder zapcore.ArrayEncoder) error { 27 if len(abb) <= 4 { 28 for _, e := range abb { 29 encoder.AppendString(e) 30 } 31 } else { 32 total := len(abb) 33 encoder.AppendString(abb[0]) 34 encoder.AppendString(fmt.Sprintf("(skip %d)", total-2)) 35 encoder.AppendString(abb[total-1]) 36 } 37 return nil 38 } 39 40 // AbbreviatedArray constructs a field that abbreviates an array of elements. 41 func AbbreviatedArray( 42 key string, elements interface{}, marshalFunc func(interface{}) []string, 43 ) zap.Field { 44 return zap.Array(key, AbbreviatedArrayMarshaler(marshalFunc(elements))) 45 } 46 47 type zapFileMarshaler struct{ *backuppb.File } 48 49 func (file zapFileMarshaler) MarshalLogObject(enc zapcore.ObjectEncoder) error { 50 enc.AddString("name", file.GetName()) 51 enc.AddString("CF", file.GetCf()) 52 enc.AddString("sha256", hex.EncodeToString(file.GetSha256())) 53 enc.AddString("startKey", redact.Key(file.GetStartKey())) 54 enc.AddString("endKey", redact.Key(file.GetEndKey())) 55 enc.AddUint64("startVersion", file.GetStartVersion()) 56 enc.AddUint64("endVersion", file.GetEndVersion()) 57 enc.AddUint64("totalKvs", file.GetTotalKvs()) 58 enc.AddUint64("totalBytes", file.GetTotalBytes()) 59 enc.AddUint64("CRC64Xor", file.GetCrc64Xor()) 60 return nil 61 } 62 63 type zapFilesMarshaler []*backuppb.File 64 65 func (fs zapFilesMarshaler) MarshalLogObject(encoder zapcore.ObjectEncoder) error { 66 total := len(fs) 67 encoder.AddInt("total", total) 68 elements := make([]string, 0, total) 69 for _, f := range fs { 70 elements = append(elements, f.GetName()) 71 } 72 _ = encoder.AddArray("files", AbbreviatedArrayMarshaler(elements)) 73 74 totalKVs := uint64(0) 75 totalBytes := uint64(0) 76 totalSize := uint64(0) 77 for _, file := range fs { 78 totalKVs += file.GetTotalKvs() 79 totalBytes += file.GetTotalBytes() 80 totalSize += file.GetSize_() 81 } 82 encoder.AddUint64("totalKVs", totalKVs) 83 encoder.AddUint64("totalBytes", totalBytes) 84 encoder.AddUint64("totalSize", totalSize) 85 return nil 86 } 87 88 // File make the zap fields for a file. 89 func File(file *backuppb.File) zap.Field { 90 return zap.Object("file", zapFileMarshaler{file}) 91 } 92 93 // Files make the zap field for a set of file. 94 func Files(fs []*backuppb.File) zap.Field { 95 return zap.Object("files", zapFilesMarshaler(fs)) 96 } 97 98 type zapRewriteRuleMarshaler struct{ *import_sstpb.RewriteRule } 99 100 func (rewriteRule zapRewriteRuleMarshaler) MarshalLogObject(enc zapcore.ObjectEncoder) error { 101 enc.AddString("oldKeyPrefix", hex.EncodeToString(rewriteRule.GetOldKeyPrefix())) 102 enc.AddString("newKeyPrefix", hex.EncodeToString(rewriteRule.GetNewKeyPrefix())) 103 enc.AddUint64("newTimestamp", rewriteRule.GetNewTimestamp()) 104 return nil 105 } 106 107 // RewriteRule make the zap fields for a rewrite rule. 108 func RewriteRule(rewriteRule *import_sstpb.RewriteRule) zap.Field { 109 return zap.Object("rewriteRule", zapRewriteRuleMarshaler{rewriteRule}) 110 } 111 112 type zapMarshalRegionMarshaler struct{ *metapb.Region } 113 114 func (region zapMarshalRegionMarshaler) MarshalLogObject(enc zapcore.ObjectEncoder) error { 115 peers := make([]string, 0, len(region.GetPeers())) 116 for _, peer := range region.GetPeers() { 117 peers = append(peers, peer.String()) 118 } 119 enc.AddUint64("ID", region.Id) 120 enc.AddString("startKey", redact.Key(region.GetStartKey())) 121 enc.AddString("endKey", redact.Key(region.GetEndKey())) 122 enc.AddString("epoch", region.GetRegionEpoch().String()) 123 enc.AddString("peers", strings.Join(peers, ",")) 124 return nil 125 } 126 127 // Region make the zap fields for a region. 128 func Region(region *metapb.Region) zap.Field { 129 return zap.Object("region", zapMarshalRegionMarshaler{region}) 130 } 131 132 // RegionBy make the zap fields for a region with name. 133 func RegionBy(key string, region *metapb.Region) zap.Field { 134 return zap.Object(key, zapMarshalRegionMarshaler{region}) 135 } 136 137 // Leader make the zap fields for a peer. 138 // nolint:interfacer 139 func Leader(peer *metapb.Peer) zap.Field { 140 return zap.String("leader", peer.String()) 141 } 142 143 type zapSSTMetaMarshaler struct{ *import_sstpb.SSTMeta } 144 145 func (sstMeta zapSSTMetaMarshaler) MarshalLogObject(enc zapcore.ObjectEncoder) error { 146 enc.AddString("CF", sstMeta.GetCfName()) 147 enc.AddBool("endKeyExclusive", sstMeta.EndKeyExclusive) 148 enc.AddUint32("CRC32", sstMeta.Crc32) 149 enc.AddUint64("length", sstMeta.Length) 150 enc.AddUint64("regionID", sstMeta.RegionId) 151 enc.AddString("regionEpoch", sstMeta.RegionEpoch.String()) 152 enc.AddString("startKey", redact.Key(sstMeta.GetRange().GetStart())) 153 enc.AddString("endKey", redact.Key(sstMeta.GetRange().GetEnd())) 154 155 sstUUID, err := uuid.FromBytes(sstMeta.GetUuid()) 156 if err != nil { 157 enc.AddString("UUID", fmt.Sprintf("invalid UUID %s", hex.EncodeToString(sstMeta.GetUuid()))) 158 } else { 159 enc.AddString("UUID", sstUUID.String()) 160 } 161 return nil 162 } 163 164 // SSTMeta make the zap fields for a SST meta. 165 func SSTMeta(sstMeta *import_sstpb.SSTMeta) zap.Field { 166 return zap.Object("sstMeta", zapSSTMetaMarshaler{sstMeta}) 167 } 168 169 type zapSSTMetasMarshaler []*import_sstpb.SSTMeta 170 171 func (m zapSSTMetasMarshaler) MarshalLogArray(encoder zapcore.ArrayEncoder) error { 172 for _, meta := range m { 173 if err := encoder.AppendObject(zapSSTMetaMarshaler{meta}); err != nil { 174 return errors.Trace(err) 175 } 176 } 177 return nil 178 } 179 180 // SSTMetas make the zap fields for SST metas. 181 func SSTMetas(sstMetas []*import_sstpb.SSTMeta) zap.Field { 182 return zap.Array("sstMetas", zapSSTMetasMarshaler(sstMetas)) 183 } 184 185 type zapKeysMarshaler [][]byte 186 187 func (keys zapKeysMarshaler) MarshalLogObject(encoder zapcore.ObjectEncoder) error { 188 total := len(keys) 189 encoder.AddInt("total", total) 190 elements := make([]string, 0, total) 191 for _, k := range keys { 192 elements = append(elements, redact.Key(k)) 193 } 194 _ = encoder.AddArray("keys", AbbreviatedArrayMarshaler(elements)) 195 return nil 196 } 197 198 // Key constructs a field that carries upper hex format key. 199 func Key(fieldKey string, key []byte) zap.Field { 200 return zap.String(fieldKey, redact.Key(key)) 201 } 202 203 // Keys constructs a field that carries upper hex format keys. 204 func Keys(keys [][]byte) zap.Field { 205 return zap.Object("keys", zapKeysMarshaler(keys)) 206 } 207 208 // ShortError make the zap field to display error without verbose representation (e.g. the stack trace). 209 func ShortError(err error) zap.Field { 210 return zap.String("error", err.Error()) 211 } 212 213 var loggerToTerm, _, _ = log.InitLogger(new(log.Config), zap.AddCallerSkip(1)) 214 215 // WarnTerm put a log both to terminal and to the log file. 216 func WarnTerm(message string, fields ...zap.Field) { 217 log.Warn(message, fields...) 218 if loggerToTerm != nil { 219 loggerToTerm.Warn(message, fields...) 220 } 221 } 222 223 // RedactAny constructs a redacted field that carries an interface{}. 224 func RedactAny(fieldKey string, key interface{}) zap.Field { 225 if redact.NeedRedact() { 226 return zap.String(fieldKey, "?") 227 } 228 return zap.Any(fieldKey, key) 229 }