raft_internal_stringer.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  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. package etcdserverpb
  15. import (
  16. "fmt"
  17. "strings"
  18. proto "github.com/golang/protobuf/proto"
  19. )
  20. // InternalRaftStringer implements custom proto Stringer:
  21. // redact password, replace value fields with value_size fields.
  22. type InternalRaftStringer struct {
  23. Request *InternalRaftRequest
  24. }
  25. func (as *InternalRaftStringer) String() string {
  26. switch {
  27. case as.Request.LeaseGrant != nil:
  28. return fmt.Sprintf("header:<%s> lease_grant:<ttl:%d-second id:%016x>",
  29. as.Request.Header.String(),
  30. as.Request.LeaseGrant.TTL,
  31. as.Request.LeaseGrant.ID,
  32. )
  33. case as.Request.LeaseRevoke != nil:
  34. return fmt.Sprintf("header:<%s> lease_revoke:<id:%016x>",
  35. as.Request.Header.String(),
  36. as.Request.LeaseRevoke.ID,
  37. )
  38. case as.Request.Authenticate != nil:
  39. return fmt.Sprintf("header:<%s> authenticate:<name:%s simple_token:%s>",
  40. as.Request.Header.String(),
  41. as.Request.Authenticate.Name,
  42. as.Request.Authenticate.SimpleToken,
  43. )
  44. case as.Request.AuthUserAdd != nil:
  45. return fmt.Sprintf("header:<%s> auth_user_add:<name:%s>",
  46. as.Request.Header.String(),
  47. as.Request.AuthUserAdd.Name,
  48. )
  49. case as.Request.AuthUserChangePassword != nil:
  50. return fmt.Sprintf("header:<%s> auth_user_change_password:<name:%s>",
  51. as.Request.Header.String(),
  52. as.Request.AuthUserChangePassword.Name,
  53. )
  54. case as.Request.Put != nil:
  55. return fmt.Sprintf("header:<%s> put:<%s>",
  56. as.Request.Header.String(),
  57. NewLoggablePutRequest(as.Request.Put).String(),
  58. )
  59. case as.Request.Txn != nil:
  60. return fmt.Sprintf("header:<%s> txn:<%s>",
  61. as.Request.Header.String(),
  62. NewLoggableTxnRequest(as.Request.Txn).String(),
  63. )
  64. default:
  65. // nothing to redact
  66. }
  67. return as.Request.String()
  68. }
  69. // txnRequestStringer implements a custom proto String to replace value bytes fields with value size
  70. // fields in any nested txn and put operations.
  71. type txnRequestStringer struct {
  72. Request *TxnRequest
  73. }
  74. func NewLoggableTxnRequest(request *TxnRequest) *txnRequestStringer {
  75. return &txnRequestStringer{request}
  76. }
  77. func (as *txnRequestStringer) String() string {
  78. var compare []string
  79. for _, c := range as.Request.Compare {
  80. switch cv := c.TargetUnion.(type) {
  81. case *Compare_Value:
  82. compare = append(compare, newLoggableValueCompare(c, cv).String())
  83. default:
  84. // nothing to redact
  85. compare = append(compare, c.String())
  86. }
  87. }
  88. var success []string
  89. for _, s := range as.Request.Success {
  90. success = append(success, newLoggableRequestOp(s).String())
  91. }
  92. var failure []string
  93. for _, f := range as.Request.Failure {
  94. failure = append(failure, newLoggableRequestOp(f).String())
  95. }
  96. return fmt.Sprintf("compare:<%s> success:<%s> failure:<%s>",
  97. strings.Join(compare, " "),
  98. strings.Join(success, " "),
  99. strings.Join(failure, " "),
  100. )
  101. }
  102. // requestOpStringer implements a custom proto String to replace value bytes fields with value
  103. // size fields in any nested txn and put operations.
  104. type requestOpStringer struct {
  105. Op *RequestOp
  106. }
  107. func newLoggableRequestOp(op *RequestOp) *requestOpStringer {
  108. return &requestOpStringer{op}
  109. }
  110. func (as *requestOpStringer) String() string {
  111. switch op := as.Op.Request.(type) {
  112. case *RequestOp_RequestPut:
  113. return fmt.Sprintf("request_put:<%s>", NewLoggablePutRequest(op.RequestPut).String())
  114. case *RequestOp_RequestTxn:
  115. return fmt.Sprintf("request_txn:<%s>", NewLoggableTxnRequest(op.RequestTxn).String())
  116. default:
  117. // nothing to redact
  118. }
  119. return as.Op.String()
  120. }
  121. // loggableValueCompare implements a custom proto String for Compare.Value union member types to
  122. // replace the value bytes field with a value size field.
  123. // To preserve proto encoding of the key and range_end bytes, a faked out proto type is used here.
  124. type loggableValueCompare struct {
  125. Result Compare_CompareResult `protobuf:"varint,1,opt,name=result,proto3,enum=etcdserverpb.Compare_CompareResult"`
  126. Target Compare_CompareTarget `protobuf:"varint,2,opt,name=target,proto3,enum=etcdserverpb.Compare_CompareTarget"`
  127. Key []byte `protobuf:"bytes,3,opt,name=key,proto3"`
  128. ValueSize int `protobuf:"bytes,7,opt,name=value_size,proto3"`
  129. RangeEnd []byte `protobuf:"bytes,64,opt,name=range_end,proto3"`
  130. }
  131. func newLoggableValueCompare(c *Compare, cv *Compare_Value) *loggableValueCompare {
  132. return &loggableValueCompare{
  133. c.Result,
  134. c.Target,
  135. c.Key,
  136. len(cv.Value),
  137. c.RangeEnd,
  138. }
  139. }
  140. func (m *loggableValueCompare) Reset() { *m = loggableValueCompare{} }
  141. func (m *loggableValueCompare) String() string { return proto.CompactTextString(m) }
  142. func (*loggableValueCompare) ProtoMessage() {}
  143. // loggablePutRequest implements a custom proto String to replace value bytes field with a value
  144. // size field.
  145. // To preserve proto encoding of the key bytes, a faked out proto type is used here.
  146. type loggablePutRequest struct {
  147. Key []byte `protobuf:"bytes,1,opt,name=key,proto3"`
  148. ValueSize int `protobuf:"varint,2,opt,name=value_size,proto3"`
  149. Lease int64 `protobuf:"varint,3,opt,name=lease,proto3"`
  150. PrevKv bool `protobuf:"varint,4,opt,name=prev_kv,proto3"`
  151. IgnoreValue bool `protobuf:"varint,5,opt,name=ignore_value,proto3"`
  152. IgnoreLease bool `protobuf:"varint,6,opt,name=ignore_lease,proto3"`
  153. }
  154. func NewLoggablePutRequest(request *PutRequest) *loggablePutRequest {
  155. return &loggablePutRequest{
  156. request.Key,
  157. len(request.Value),
  158. request.Lease,
  159. request.PrevKv,
  160. request.IgnoreValue,
  161. request.IgnoreLease,
  162. }
  163. }
  164. func (m *loggablePutRequest) Reset() { *m = loggablePutRequest{} }
  165. func (m *loggablePutRequest) String() string { return proto.CompactTextString(m) }
  166. func (*loggablePutRequest) ProtoMessage() {}