From 894037ac7433aa6f2ba94d0277b4e71dd4c46655 Mon Sep 17 00:00:00 2001 From: JmPotato Date: Mon, 15 Nov 2021 14:08:58 +0800 Subject: [PATCH] Print the Region key with a more readable format (#375) Signed-off-by: JmPotato --- internal/locate/region_cache.go | 10 +++--- util/misc.go | 56 +++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/internal/locate/region_cache.go b/internal/locate/region_cache.go index 674adf5a..16028640 100644 --- a/internal/locate/region_cache.go +++ b/internal/locate/region_cache.go @@ -767,7 +767,7 @@ func (c *RegionCache) findRegionByKey(bo *retry.Backoffer, key []byte, isEndKey if err != nil { // ignore error and use old region info. logutil.Logger(bo.GetCtx()).Error("load region failure", - zap.ByteString("key", key), zap.Error(err)) + zap.String("key", util.HexRegionKeyStr(key)), zap.Error(err)) } else { logutil.Eventf(bo.GetCtx(), "load region %d from pd, due to need-reload", lr.GetID()) r = lr @@ -1257,13 +1257,13 @@ func (c *RegionCache) loadRegion(bo *retry.Backoffer, key []byte, isEndKey bool) } if err != nil { if isDecodeError(err) { - return nil, errors.Errorf("failed to decode region range key, key: %q, err: %v", key, err) + return nil, errors.Errorf("failed to decode region range key, key: %q, err: %v", util.HexRegionKeyStr(key), err) } - backoffErr = errors.Errorf("loadRegion from PD failed, key: %q, err: %v", key, err) + backoffErr = errors.Errorf("loadRegion from PD failed, key: %q, err: %v", util.HexRegionKeyStr(key), err) continue } if reg == nil || reg.Meta == nil { - backoffErr = errors.Errorf("region not found for key %q", key) + backoffErr = errors.Errorf("region not found for key %q", util.HexRegionKeyStr(key)) continue } filterUnavailablePeers(reg) @@ -1358,7 +1358,7 @@ func (c *RegionCache) scanRegions(bo *retry.Backoffer, startKey, endKey []byte, regionsInfo, err := c.pdClient.ScanRegions(ctx, startKey, endKey, limit) if err != nil { if isDecodeError(err) { - return nil, errors.Errorf("failed to decode region range key, startKey: %q, limit: %q, err: %v", startKey, limit, err) + return nil, errors.Errorf("failed to decode region range key, startKey: %q, limit: %q, err: %v", util.HexRegionKeyStr(startKey), limit, err) } metrics.RegionCacheCounterWithScanRegionsError.Inc() backoffErr = errors.Errorf( diff --git a/util/misc.go b/util/misc.go index 3be30765..61b643f4 100644 --- a/util/misc.go +++ b/util/misc.go @@ -36,10 +36,13 @@ package util import ( "context" + "encoding/hex" "fmt" + "reflect" "strconv" "strings" "time" + "unsafe" "github.com/pkg/errors" "github.com/tikv/client-go/v2/internal/logutil" @@ -154,3 +157,56 @@ func BytesToString(numBytes int64) string { return fmt.Sprintf("%v Bytes", numBytes) } + +// String converts slice of bytes to string without copy. +func String(b []byte) (s string) { + if len(b) == 0 { + return "" + } + pbytes := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + pstring := (*reflect.StringHeader)(unsafe.Pointer(&s)) + pstring.Data = pbytes.Data + pstring.Len = pbytes.Len + return +} + +// ToUpperASCIIInplace bytes.ToUpper but zero-cost +func ToUpperASCIIInplace(s []byte) []byte { + hasLower := false + for i := 0; i < len(s); i++ { + c := s[i] + hasLower = hasLower || ('a' <= c && c <= 'z') + } + + if !hasLower { + return s + } + var c byte + for i := 0; i < len(s); i++ { + c = s[i] + if 'a' <= c && c <= 'z' { + c -= 'a' - 'A' + } + s[i] = c + } + return s +} + +// EncodeToString overrides hex.EncodeToString implementation. Difference: returns []byte, not string +func EncodeToString(src []byte) []byte { + dst := make([]byte, hex.EncodedLen(len(src))) + hex.Encode(dst, src) + return dst +} + +// HexRegionKey converts region key to hex format. Used for formating region in +// logs. +func HexRegionKey(key []byte) []byte { + return ToUpperASCIIInplace(EncodeToString(key)) +} + +// HexRegionKeyStr converts region key to hex format. Used for formating region in +// logs. +func HexRegionKeyStr(key []byte) string { + return String(HexRegionKey(key)) +}