mirror of https://github.com/tikv/client-go.git
142 lines
2.9 KiB
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
|
|
}
|
|
}
|
|
}
|
|
}
|