go.etcd.io/etcd@v3.3.27+incompatible/etcdserver/etcdserverpb/raft_internal_stringer.go (about)

     1  // Copyright 2018 The etcd Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package etcdserverpb
    16  
    17  import (
    18  	"fmt"
    19  	"strings"
    20  
    21  	proto "github.com/golang/protobuf/proto"
    22  )
    23  
    24  // InternalRaftStringer implements custom proto Stringer:
    25  // redact password, replace value fields with value_size fields.
    26  type InternalRaftStringer struct {
    27  	Request *InternalRaftRequest
    28  }
    29  
    30  func (as *InternalRaftStringer) String() string {
    31  	switch {
    32  	case as.Request.LeaseGrant != nil:
    33  		return fmt.Sprintf("header:<%s> lease_grant:<ttl:%d-second id:%016x>",
    34  			as.Request.Header.String(),
    35  			as.Request.LeaseGrant.TTL,
    36  			as.Request.LeaseGrant.ID,
    37  		)
    38  	case as.Request.LeaseRevoke != nil:
    39  		return fmt.Sprintf("header:<%s> lease_revoke:<id:%016x>",
    40  			as.Request.Header.String(),
    41  			as.Request.LeaseRevoke.ID,
    42  		)
    43  	case as.Request.Authenticate != nil:
    44  		return fmt.Sprintf("header:<%s> authenticate:<name:%s simple_token:%s>",
    45  			as.Request.Header.String(),
    46  			as.Request.Authenticate.Name,
    47  			as.Request.Authenticate.SimpleToken,
    48  		)
    49  	case as.Request.AuthUserAdd != nil:
    50  		return fmt.Sprintf("header:<%s> auth_user_add:<name:%s>",
    51  			as.Request.Header.String(),
    52  			as.Request.AuthUserAdd.Name,
    53  		)
    54  	case as.Request.AuthUserChangePassword != nil:
    55  		return fmt.Sprintf("header:<%s> auth_user_change_password:<name:%s>",
    56  			as.Request.Header.String(),
    57  			as.Request.AuthUserChangePassword.Name,
    58  		)
    59  	case as.Request.Put != nil:
    60  		return fmt.Sprintf("header:<%s> put:<%s>",
    61  			as.Request.Header.String(),
    62  			NewLoggablePutRequest(as.Request.Put).String(),
    63  		)
    64  	case as.Request.Txn != nil:
    65  		return fmt.Sprintf("header:<%s> txn:<%s>",
    66  			as.Request.Header.String(),
    67  			NewLoggableTxnRequest(as.Request.Txn).String(),
    68  		)
    69  	default:
    70  		// nothing to redact
    71  	}
    72  	return as.Request.String()
    73  }
    74  
    75  // txnRequestStringer implements a custom proto String to replace value bytes fields with value size
    76  // fields in any nested txn and put operations.
    77  type txnRequestStringer struct {
    78  	Request *TxnRequest
    79  }
    80  
    81  func NewLoggableTxnRequest(request *TxnRequest) *txnRequestStringer {
    82  	return &txnRequestStringer{request}
    83  }
    84  
    85  func (as *txnRequestStringer) String() string {
    86  	var compare []string
    87  	for _, c := range as.Request.Compare {
    88  		switch cv := c.TargetUnion.(type) {
    89  		case *Compare_Value:
    90  			compare = append(compare, newLoggableValueCompare(c, cv).String())
    91  		default:
    92  			// nothing to redact
    93  			compare = append(compare, c.String())
    94  		}
    95  	}
    96  	var success []string
    97  	for _, s := range as.Request.Success {
    98  		success = append(success, newLoggableRequestOp(s).String())
    99  	}
   100  	var failure []string
   101  	for _, f := range as.Request.Failure {
   102  		failure = append(failure, newLoggableRequestOp(f).String())
   103  	}
   104  	return fmt.Sprintf("compare:<%s> success:<%s> failure:<%s>",
   105  		strings.Join(compare, " "),
   106  		strings.Join(success, " "),
   107  		strings.Join(failure, " "),
   108  	)
   109  }
   110  
   111  // requestOpStringer implements a custom proto String to replace value bytes fields with value
   112  // size fields in any nested txn and put operations.
   113  type requestOpStringer struct {
   114  	Op *RequestOp
   115  }
   116  
   117  func newLoggableRequestOp(op *RequestOp) *requestOpStringer {
   118  	return &requestOpStringer{op}
   119  }
   120  
   121  func (as *requestOpStringer) String() string {
   122  	switch op := as.Op.Request.(type) {
   123  	case *RequestOp_RequestPut:
   124  		return fmt.Sprintf("request_put:<%s>", NewLoggablePutRequest(op.RequestPut).String())
   125  	case *RequestOp_RequestTxn:
   126  		return fmt.Sprintf("request_txn:<%s>", NewLoggableTxnRequest(op.RequestTxn).String())
   127  	default:
   128  		// nothing to redact
   129  	}
   130  	return as.Op.String()
   131  }
   132  
   133  // loggableValueCompare implements a custom proto String for Compare.Value union member types to
   134  // replace the value bytes field with a value size field.
   135  // To preserve proto encoding of the key and range_end bytes, a faked out proto type is used here.
   136  type loggableValueCompare struct {
   137  	Result    Compare_CompareResult `protobuf:"varint,1,opt,name=result,proto3,enum=etcdserverpb.Compare_CompareResult"`
   138  	Target    Compare_CompareTarget `protobuf:"varint,2,opt,name=target,proto3,enum=etcdserverpb.Compare_CompareTarget"`
   139  	Key       []byte                `protobuf:"bytes,3,opt,name=key,proto3"`
   140  	ValueSize int64                 `protobuf:"varint,7,opt,name=value_size,proto3"`
   141  	RangeEnd  []byte                `protobuf:"bytes,64,opt,name=range_end,proto3"`
   142  }
   143  
   144  func newLoggableValueCompare(c *Compare, cv *Compare_Value) *loggableValueCompare {
   145  	return &loggableValueCompare{
   146  		c.Result,
   147  		c.Target,
   148  		c.Key,
   149  		int64(len(cv.Value)),
   150  		c.RangeEnd,
   151  	}
   152  }
   153  
   154  func (m *loggableValueCompare) Reset()         { *m = loggableValueCompare{} }
   155  func (m *loggableValueCompare) String() string { return proto.CompactTextString(m) }
   156  func (*loggableValueCompare) ProtoMessage()    {}
   157  
   158  // loggablePutRequest implements a custom proto String to replace value bytes field with a value
   159  // size field.
   160  // To preserve proto encoding of the key bytes, a faked out proto type is used here.
   161  type loggablePutRequest struct {
   162  	Key         []byte `protobuf:"bytes,1,opt,name=key,proto3"`
   163  	ValueSize   int64  `protobuf:"varint,2,opt,name=value_size,proto3"`
   164  	Lease       int64  `protobuf:"varint,3,opt,name=lease,proto3"`
   165  	PrevKv      bool   `protobuf:"varint,4,opt,name=prev_kv,proto3"`
   166  	IgnoreValue bool   `protobuf:"varint,5,opt,name=ignore_value,proto3"`
   167  	IgnoreLease bool   `protobuf:"varint,6,opt,name=ignore_lease,proto3"`
   168  }
   169  
   170  func NewLoggablePutRequest(request *PutRequest) *loggablePutRequest {
   171  	return &loggablePutRequest{
   172  		request.Key,
   173  		int64(len(request.Value)),
   174  		request.Lease,
   175  		request.PrevKv,
   176  		request.IgnoreValue,
   177  		request.IgnoreLease,
   178  	}
   179  }
   180  
   181  func (m *loggablePutRequest) Reset()         { *m = loggablePutRequest{} }
   182  func (m *loggablePutRequest) String() string { return proto.CompactTextString(m) }
   183  func (*loggablePutRequest) ProtoMessage()    {}