github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/pkg/util/server/recovery.go (about)

     1  package server
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"os"
     7  	"runtime"
     8  
     9  	grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery"
    10  	"github.com/prometheus/client_golang/prometheus"
    11  	"github.com/prometheus/client_golang/prometheus/promauto"
    12  	"github.com/weaveworks/common/httpgrpc"
    13  	"github.com/weaveworks/common/middleware"
    14  )
    15  
    16  const maxStacksize = 8 * 1024
    17  
    18  var (
    19  	panicTotal = promauto.NewCounter(prometheus.CounterOpts{
    20  		Namespace: "loki",
    21  		Name:      "panic_total",
    22  		Help:      "The total number of panic triggered",
    23  	})
    24  
    25  	RecoveryHTTPMiddleware = middleware.Func(func(next http.Handler) http.Handler {
    26  		return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
    27  			defer func() {
    28  				if p := recover(); p != nil {
    29  					WriteError(onPanic(p), w)
    30  				}
    31  			}()
    32  			next.ServeHTTP(w, req)
    33  		})
    34  	})
    35  	RecoveryGRPCStreamInterceptor = grpc_recovery.StreamServerInterceptor(grpc_recovery.WithRecoveryHandler(onPanic))
    36  	RecoveryGRPCUnaryInterceptor  = grpc_recovery.UnaryServerInterceptor(grpc_recovery.WithRecoveryHandler(onPanic))
    37  )
    38  
    39  func onPanic(p interface{}) error {
    40  	stack := make([]byte, maxStacksize)
    41  	stack = stack[:runtime.Stack(stack, true)]
    42  	// keep a multiline stack
    43  	fmt.Fprintf(os.Stderr, "panic: %v\n%s", p, stack)
    44  	panicTotal.Inc()
    45  	return httpgrpc.Errorf(http.StatusInternalServerError, "error while processing request: %v", p)
    46  }