github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/storage/error.go (about) 1 // Copyright 2017 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package storage 12 13 import ( 14 "regexp" 15 "strings" 16 17 "github.com/cockroachdb/errors" 18 ) 19 20 // A Error wraps an error returned from a RocksDB operation. 21 type Error struct { 22 msg string 23 } 24 25 var _ errors.SafeMessager = (*Error)(nil) 26 27 // Error implements the error interface. 28 func (err *Error) Error() string { 29 return err.msg 30 } 31 32 // SafeMessage implements log.SafeMessager. RocksDB errors are not very 33 // well-structured and we additionally only pass a stringified representation 34 // from C++ to Go. The error usually takes the form "<typeStr>: [<subtypeStr>] 35 // <msg>" where `<typeStr>` is generated from an enum and <subtypeStr> is rarely 36 // used. <msg> usually contains the bulk of information and follows no 37 // particular rules. 38 // 39 // To extract safe messages from these errors, we keep a dictionary generated 40 // from the RocksDB source code and report verbatim all words from the 41 // dictionary (masking out the rest which in particular includes paths). 42 // 43 // The originating RocksDB error type is defined in 44 // c-deps/rocksdb/util/status.cc. 45 func (err Error) SafeMessage() string { 46 var out []string 47 // NB: we leave (unix and windows style) directory separators in the cleaned 48 // string to avoid a directory such as /mnt/rocksdb/known/words from showing 49 // up. The dictionary is all [a-zA-Z], so anything that has a separator left 50 // within after cleaning is going to be redacted. 51 cleanRE := regexp.MustCompile(`[^a-zA-Z\/\\]+`) 52 for _, field := range strings.Fields(err.msg) { 53 word := strings.ToLower(cleanRE.ReplaceAllLiteralString(field, "")) 54 if _, isSafe := rocksDBErrorDict[word]; isSafe { 55 out = append(out, word) 56 } else { 57 out = append(out, "<redacted>") 58 } 59 } 60 return strings.Join(out, " ") 61 }