client-go/util/redact/redact.go

142 lines
2.9 KiB
Go

package redact
import (
"encoding/hex"
"unsafe"
"github.com/pingcap/errors"
"github.com/pingcap/kvproto/pkg/kvrpcpb"
)
// NeedRedact returns whether to redact log
func NeedRedact() bool {
mode := errors.RedactLogEnabled.Load()
return mode != errors.RedactLogDisable && mode != ""
}
// Key receives a key return omitted information if redact log enabled
func Key(key []byte) string {
if NeedRedact() {
return "?"
}
return String(toUpperASCIIInplace(encodeToString(key)))
}
// KeyBytes receives a key return omitted information if redact log enabled
func KeyBytes(key []byte) []byte {
if NeedRedact() {
return []byte{'?'}
}
return toUpperASCIIInplace(encodeToString(key))
}
// String converts slice of bytes to string without copy.
func String(b []byte) (s string) {
if len(b) == 0 {
return ""
}
return unsafe.String(unsafe.SliceData(b), len(b))
}
// 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
}
// 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
}
// RedactKeyErrIfNecessary redact the key in *kvrpcpb.KeyError.
func RedactKeyErrIfNecessary(err *kvrpcpb.KeyError) {
if !NeedRedact() {
return
}
redactMarker := []byte{'?'}
if e := err.Locked; e != nil {
if len(e.PrimaryLock) > 0 {
e.PrimaryLock = redactMarker
}
if len(e.Key) > 0 {
e.Key = redactMarker
}
for i := range e.Secondaries {
e.Secondaries[i] = redactMarker
}
}
if e := err.Conflict; e != nil {
if len(e.Key) > 0 {
e.Key = redactMarker
}
if len(e.Primary) > 0 {
e.Primary = redactMarker
}
}
if e := err.AlreadyExist; e != nil {
if len(e.Key) > 0 {
e.Key = redactMarker
}
}
if e := err.Deadlock; e != nil {
if len(e.LockKey) > 0 {
e.LockKey = redactMarker
}
if len(e.DeadlockKey) > 0 {
e.DeadlockKey = redactMarker
}
for i := range e.WaitChain {
if len(e.WaitChain[i].Key) > 0 {
e.WaitChain[i].Key = redactMarker
}
}
}
if e := err.CommitTsExpired; e != nil {
if len(e.Key) > 0 {
e.Key = redactMarker
}
}
if e := err.TxnNotFound; e != nil {
if len(e.PrimaryKey) > 0 {
e.PrimaryKey = redactMarker
}
}
if e := err.AssertionFailed; e != nil {
if len(e.Key) > 0 {
e.Key = redactMarker
}
}
if mismatchErr := err.PrimaryMismatch; mismatchErr != nil {
if e := mismatchErr.LockInfo; e != nil {
if len(e.PrimaryLock) > 0 {
e.PrimaryLock = redactMarker
}
if len(e.Key) > 0 {
e.Key = redactMarker
}
for i := range e.Secondaries {
e.Secondaries[i] = redactMarker
}
}
}
}