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]