fishy commented on pull request #1992:
URL: https://github.com/apache/thrift/pull/1992#issuecomment-705903922


   Since the only gap between interceptor idea and already existing middleware 
are the requests/responses, here's an idea to add that ability, without any 
compiler changes (this can even be from a third party library, it doesn't use 
any unexported function from the thrift library).
   
   First you just need to implement a `RecordingTProtocol` (name TBD, it can 
also be `InterceptorTProtocol` if you like):
   
   ```go
   type RecordingTProtocol struct {
     Recording, Actual TProtocol
   }
   
   func (rp RecordingTProtocol) ReadMessageBegin() (name string, typeId 
TMessageType, seqid int32, err error) {
     name, typeId, seqid, err = rp.Actual.ReadMessageBegin()
     if err != nil {
       err = rp.Recording.WriteMessageBegin(name, typeId, seqid)
     }
   }
   
   // TODO: implement other TProtocol read functions
   
   func (rp RecordingTProtocol) WriteMessageBegin(name string, typeId 
TMessageType, seqid int32) (err error) {
     rp.Recording.WriteMessageBegin(name, typeId, seqid)
     err = rp.Actual.WriteMessageBegin(name, typeId, seqid)
   }
   
   // TODO: implement other TProtocol write functions
   ```
   
   Then you can just use it in a middleware implementation and combine it with 
`TMemoryBuffer` as the underlying `TTransport` for the recording one. For 
example for json logging:
   
   ```go
   func loggingMiddleware(next thrift.TClient) thrift.TClient {
     return thrift.WrappedTClient{
       Wrapped: func(ctx context.Context, method string, args, result 
thrift.TStruct) (err error) {
         // TODO: use resource pool
         inBuf := thrift.NewTMemoryBuffer()
         inProto := thrift.NewTSimpleJSONProtocol(inBuf)
         outBuf := thrift.NewTMemoryBuffer()
         outProto := thrift.NewTSimpleJSONProtocol(outBuf)
         defer func() {
           logger("name", method, "request", inBuf.String(), "response", 
outBuf.String, "error", err)
         }()
         return next.Call(
           ctx,
           method,
           RecordingTProtocol{Actual: args, Recording: inProto},
           RecordingTProtocol{Actual: result, Recording: outProto},
         )
       },
     }
   }
   ```
   
   And I can also use it to record the size on the wire (also I think this is 
inefficient and it's better done in envoy/etc.):
   
   ```go
   func sizeReportingMiddleware(next thrift.TClient) thrift.TClient {
     return thrift.WrappedTClient{
       Wrapped: func(ctx context.Context, method string, args, result 
thrift.TStruct) (err error) {
         // TODO: use resource pool
         inBuf := thrift.NewTMemoryBuffer()
         inProto := thrift.NewTHeaderProtocol(inBuf)
         outBuf := thrift.NewTMemoryBuffer()
         outProto := thrift.NewTHeaderProtocol(outBuf)
         defer func() {
           requestSizeHistogram.Observe(inBuf.Len())
           responseSizeHistogram.Observe(outBuf.Len())
         }()
         return next.Call(
           ctx,
           method,
           RecordingTProtocol{Actual: args, Recording: inProto},
           RecordingTProtocol{Actual: result, Recording: outProto},
         )
       },
     }
   }
   ```
   
   If people find it useful I can totally just implement this 
`RecordingTProtocol` in thrift library.


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to