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  }