voodoo-dn commented on pull request #1992:
URL: https://github.com/apache/thrift/pull/1992#issuecomment-705480455


   @fishy Hi. Every our Golang project in our company uses Thrift Fork with 
interceptor. They allow us following features:
   
   - Catch panic and return TApplicationException instead of EOF
   - Log incoming/outgoing request/response
   - Tracing
   - Catch and log error
   - Collect metrics for Prometheus
   - Whatever what you want :)
   
   ```
   func NewLoggerInterceptor(logger *logging.Logger, serviceName string) 
thrift.HandlerInterceptor {
        return func(ctx context.Context, methodName string, arg interface{}, 
handlerFunc thrift.HandlerFunc) (result interface{}, err error) {
                defer func() {
                        if err := recover(); err != nil {
                                log(
                                        ctx,
                                        logger,
                                        serviceName,
                                        methodName,
                                        "panicked thrift request",
                                        map[string]interface{}{
                                                "args": maskArg(ctx, logger, 
arg),
                                        },
                                )
   
                                panic(err)
                        }
                }()
   
                handlerResult, handlerError := handlerFunc(ctx, arg)
   
                handlerResultData, handlerResultMarshalErr := 
json.Marshal(handlerResult)
                if handlerResultMarshalErr != nil {
                        logger.Error(ctx, handlerResultMarshalErr)
                }
   
                log(
                        ctx,
                        logger,
                        serviceName,
                        methodName,
                        "thrift request",
                        map[string]interface{}{
                                "args":   maskArg(ctx, logger, arg),
                                "result": string(handlerResultData),
                        },
                )
   
                return handlerResult, handlerError
        }
   }
   
   func NewPanicInterceptor(logger *logging.Logger) thrift.HandlerInterceptor {
        return func(ctx context.Context, methodName string, arg interface{}, 
handlerFunc thrift.HandlerFunc) (result interface{}, err error) {
                defer func() {
                        if rec := recover(); rec != nil {
                                logger.Error(ctx, errors.New(fmt.Sprint(rec)))
   
                                err = 
thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "Internal server error")
                        }
                }()
   
                return handlerFunc(ctx, arg)
        }
   }
   
   func NewTracingInterceptor(
        tracer opentracing.Tracer,
        parentSpan opentracing.Span,
        serviceName string,
   ) thrift.HandlerInterceptor {
        return func(ctx context.Context, methodName string, arg interface{}, 
handlerFunc thrift.HandlerFunc) (interface{}, error) {
                span := tracer.StartSpan(
                        fmt.Sprintf("%s:%s", serviceName, methodName),
                        opentracing.ChildOf(parentSpan.Context()),
                )
                defer span.Finish()
                ctx = opentracing.ContextWithSpan(ctx, span)
                var correlationID string
                if span, ok := span.(*jaeger.Span); ok {
                        correlationID = span.SpanContext().TraceID().String()
                        ctx = processor.WithCorrelationID(ctx, correlationID)
                }
   
                result, err := handlerFunc(ctx, arg)
                if err != nil {
                        span.SetTag("error", true)
                }
   
                return result, err
        }
   }
   
   // Wrap all errors with UnexpectedError except api errors that implement 
thrift.TStruct
   func NewErrorInterceptor(serviceName string, logger *logging.Logger) 
thrift.HandlerInterceptor {
        return func(ctx context.Context, methodName string, arg interface{}, 
handlerFunc thrift.HandlerFunc) (interface{}, error) {
                result, err := handlerFunc(ctx, arg)
                if err == nil {
                        return result, nil
                }
   
                logger = logger.WithFields(logging.Fields{
                        "service": serviceName,
                        "method":  methodName,
                        "request": maskArg(ctx, logger, arg),
                })
   
                if _, ok := err.(thrift.TStruct); ok {
                        logger.Info(ctx, err)
                } else {
                        logger.Error(ctx, err)
                        err = NewUnexpectedError(err)
                }
   
                return result, err
        }
   }
   ```


----------------------------------------------------------------
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