github.com/amazechain/amc@v0.1.3/internal/sync/messagehandler.go (about) 1 // Package messagehandler contains useful helpers for recovering 2 // from panic conditions at runtime and logging their trace. 3 package sync 4 5 import ( 6 "context" 7 "fmt" 8 amcLog "github.com/amazechain/amc/log" 9 "go.opencensus.io/trace" 10 "runtime/debug" 11 12 pubsub "github.com/libp2p/go-libp2p-pubsub" 13 ) 14 15 const noMsgData = "message contains no data" 16 17 var messageLog = amcLog.New("prefix", "message-handler") 18 19 // SafelyHandleMessage will recover and log any panic that occurs from the 20 // function argument. 21 func (s *Service) safelyHandleMessage(ctx context.Context, fn func(ctx context.Context, message *pubsub.Message) error, msg *pubsub.Message) { 22 defer s.handlePanic(ctx, msg) 23 24 // Fingers crossed that it doesn't panic... 25 if err := fn(ctx, msg); err != nil { 26 // Report any error on the span, if one exists. 27 if span := trace.FromContext(ctx); span != nil { 28 span.SetStatus(trace.Status{ 29 Code: trace.StatusCodeInternal, 30 Message: err.Error(), 31 }) 32 } 33 } 34 } 35 36 // HandlePanic returns a panic handler function that is used to 37 // capture a panic. 38 func (s *Service) handlePanic(ctx context.Context, msg *pubsub.Message) { 39 if r := recover(); r != nil { 40 printedMsg := noMsgData 41 if msg != nil { 42 printedMsg = msg.String() 43 } 44 messageLog.Error("Panicked when handling p2p message! Recovering...", "r", r, "msg", printedMsg) 45 46 debug.PrintStack() 47 48 if ctx == nil { 49 return 50 } 51 if span := trace.FromContext(ctx); span != nil { 52 span.SetStatus(trace.Status{ 53 Code: trace.StatusCodeInternal, 54 Message: fmt.Sprintf("Panic: %v", r), 55 }) 56 } 57 } 58 }