fishy edited a comment 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
   var pool = sync.Pool{
     New: func() interface{} {
       return thrift.NewTMemoryBuffer()
     },
   }
   
   func loggingMiddleware(name string, next thrift.TProcessorFunction) 
thrift.TProcessorFunction {
     return thrift.WrappedTProcessorFunction{
       Wrapped: func(ctx context.Context, seqID int32, in, out 
thrift.TProtocol) (_ bool, err thrift.TException) {
         inBuf := pool.Get().(*thrift.TMemoryBuffer)
         inBuf.Reset()
         iproto := thrift.NewTSimpleJSONProtocol(inBuf)
         // Since in thrift compiled Processor functions, we call 
ReadMessageBegin
         // before calling the actual processor, we will have the 
ReadMessageEnd at
         // the end without the pairing ReadMessageBegin call, and that will 
cause
         // TSimpleJSONProtocol to panic.
         iproto.WriteMessageBegin(ctx, "" /* name */, thrift.CALL, seqID)
         in = TRecordingProtocol{
           Actual:    in,
           Recording: iproto,
         }
   
         outBuf := pool.Get().(*thrift.TMemoryBuffer)
         outBuf.Reset()
         oproto := thrift.NewTSimpleJSONProtocol(outBuf)
         out = TRecordingProtocol{
           Actual:    out,
           Recording: oproto,
         }
   
         defer func() {
           iproto.Flush(ctx)
           logger("method", name, "request", inBuf.String(), "response", 
outBuf.String(), "err", err)
         }()
   
         return next.Process(ctx, seqID, in, out)
       },
     }
   }
   ```
   
   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 sizeRecordingMiddleware(name string, next thrift.TProcessorFunction) 
thrift.TProcessorFunction {
     return thrift.WrappedTProcessorFunction{
       Wrapped: func(ctx context.Context, seqID int32, in, out 
thrift.TProtocol) (bool, thrift.TException) {
         inBuf := pool.Get().(*thrift.TMemoryBuffer)
         inBuf.Reset()
         outBuf := pool.Get().(*thrift.TMemoryBuffer)
         outBuf.Reset()
   
         defer func() {
           requestSizeHistogram.Observe(inBuf.Len())
           responseSizeHistogram.Observe(outBuf.Len())
           pool.Put(inBuf)
           pool.Put(outBuf)
         }()
   
         iproto := factory.GetProtocol(inBuf)
         in = TRecordingProtocol{
           Actual:    in,
           Recording: iproto,
         }
         oproto := factory.GetProtocol(outBuf)
         out = TRecordingProtocol{
           Actual:    out,
           Recording: oproto,
         }
   
         return next.Process(ctx, seqID, in, out)
       },
     }
   }
   ```
   
   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