vitess.io/vitess@v0.16.2/go/vt/vtgate/errorsanitizer/error_sanitizer.go (about)

     1  /*
     2  Copyright 2022 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package errorsanitizer
    18  
    19  import (
    20  	"regexp"
    21  )
    22  
    23  const (
    24  	// Truncate errors longer than this
    25  	maxErrorLength = 384
    26  )
    27  
    28  var (
    29  	// Remove any BindVars or Sql, and anything after it
    30  	reTruncateError = regexp.MustCompile(`[,:] BindVars:|[,:] Sql:`)
    31  
    32  	// Keep syntax error, but remove anything after it
    33  	reTruncateErrorAfterSyntaxError = regexp.MustCompile(`syntax error at position \d+`)
    34  
    35  	// Keep Duplicate entry, but replace '...' with '<val>' using reReplaceSingleQuotesWithinDuplicate regexp
    36  	reTruncateErrorAfterDuplicate = regexp.MustCompile(`Duplicate entry '(.*)' for key`)
    37  
    38  	// Keep Incorrect <type> value: '...' but replace '...' with '<val>
    39  	reRemoveIncorrectValue = regexp.MustCompile(`Incorrect [\S]+ value: '(.*)' for column`)
    40  )
    41  
    42  /* Error messages often have PII in them. That can come from vttablet or from mysql, so by the time it gets to vtgate,
    43  it's an opaque string. To avoid leaking PII into, we normalize error messages before sending them out.
    44  We remove five different sorts of strings:
    45  */
    46  
    47  // * [,:] BindVars: .*/
    48  // * [,:] Sql: '.*/'
    49  // * Anything after /syntax error at position \d+/
    50  // * Anything after /Duplicate entry/ --> replace '...' with '<val>'
    51  // * Anything with /Incorrect ... value: '...'/ replace '...' with '<val>
    52  
    53  /* We also truncate the error message at a maximum length of 256 bytes, if it's somehow longer than that after normalizing.*/
    54  
    55  func NormalizeError(str string) string {
    56  	if idx := reTruncateError.FindStringIndex(str); idx != nil {
    57  		str = str[0:idx[0]]
    58  	}
    59  	if idx := reTruncateErrorAfterSyntaxError.FindStringIndex(str); idx != nil {
    60  		str = str[0:idx[1]]
    61  	}
    62  	if idx := reTruncateErrorAfterDuplicate.FindStringSubmatchIndex(str); len(idx) >= 4 {
    63  		// replace string '...' with '<val>' to mask real values
    64  		str = str[0:idx[2]] + "<val>" + str[idx[3]:]
    65  	}
    66  	if idx := reRemoveIncorrectValue.FindStringSubmatchIndex(str); len(idx) >= 4 {
    67  		str = str[0:idx[2]] + "<val>" + str[idx[3]:]
    68  	}
    69  
    70  	if len(str) > maxErrorLength {
    71  		return str[0:maxErrorLength]
    72  	}
    73  	return str
    74  }