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  }