github.com/retailcrm/mg-bot-helper@v0.0.0-20201229112329-a17255681a84/src/error_handler.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"runtime/debug"
     7  
     8  	"github.com/getsentry/raven-go"
     9  	"github.com/gin-gonic/gin"
    10  	"github.com/pkg/errors"
    11  )
    12  
    13  type (
    14  	ErrorHandlerFunc func(recovery interface{}, c *gin.Context)
    15  )
    16  
    17  func ErrorHandler(handlers ...ErrorHandlerFunc) gin.HandlerFunc {
    18  	return func(c *gin.Context) {
    19  		defer func() {
    20  			rec := recover()
    21  			for _, handler := range handlers {
    22  				handler(rec, c)
    23  			}
    24  
    25  			if rec != nil || len(c.Errors) > 0 {
    26  				c.Abort()
    27  			}
    28  		}()
    29  
    30  		c.Next()
    31  	}
    32  }
    33  
    34  func ErrorResponseHandler() ErrorHandlerFunc {
    35  	return func(recovery interface{}, c *gin.Context) {
    36  		publicErrors := c.Errors.ByType(gin.ErrorTypePublic)
    37  		privateLen := len(c.Errors.ByType(gin.ErrorTypePrivate))
    38  		publicLen := len(publicErrors)
    39  
    40  		if privateLen == 0 && publicLen == 0 && recovery == nil {
    41  			return
    42  		}
    43  
    44  		messagesLen := publicLen
    45  		if privateLen > 0 || recovery != nil {
    46  			messagesLen++
    47  		}
    48  
    49  		messages := make([]string, messagesLen)
    50  		index := 0
    51  		for _, err := range publicErrors {
    52  			messages[index] = err.Error()
    53  			index++
    54  		}
    55  
    56  		if privateLen > 0 || recovery != nil {
    57  			messages[index] = getLocalizedMessage("error_save")
    58  		}
    59  
    60  		c.JSON(http.StatusInternalServerError, gin.H{"error": messages})
    61  	}
    62  }
    63  
    64  func ErrorCaptureHandler(client *raven.Client, errorsStacktrace bool) ErrorHandlerFunc {
    65  	return func(recovery interface{}, c *gin.Context) {
    66  		tags := map[string]string{
    67  			"endpoint": c.Request.RequestURI,
    68  		}
    69  
    70  		var (
    71  			ok   bool
    72  			conn Connection
    73  		)
    74  
    75  		connection, ok := c.Get("connection")
    76  		if ok {
    77  			conn = connection.(Connection)
    78  		}
    79  
    80  		if conn.APIURL != "" {
    81  			tags["crm"] = conn.APIURL
    82  		}
    83  
    84  		if conn.ClientID != "" {
    85  			tags["clientID"] = conn.ClientID
    86  		}
    87  
    88  		if recovery != nil {
    89  			stacktrace := raven.NewStacktrace(4, 3, nil)
    90  			recStr := fmt.Sprint(recovery)
    91  			err := errors.New(recStr)
    92  			go client.CaptureMessageAndWait(
    93  				recStr,
    94  				tags,
    95  				raven.NewException(err, stacktrace),
    96  				raven.NewHttp(c.Request),
    97  			)
    98  		}
    99  
   100  		for _, err := range c.Errors {
   101  			if errorsStacktrace {
   102  				stacktrace := NewRavenStackTrace(client, err.Err, 0)
   103  				go client.CaptureMessageAndWait(
   104  					err.Error(),
   105  					tags,
   106  					raven.NewException(err.Err, stacktrace),
   107  					raven.NewHttp(c.Request),
   108  				)
   109  			} else {
   110  				go client.CaptureErrorAndWait(err.Err, tags)
   111  			}
   112  		}
   113  	}
   114  }
   115  
   116  func PanicLogger() ErrorHandlerFunc {
   117  	return func(recovery interface{}, c *gin.Context) {
   118  		if recovery != nil {
   119  			logger.Error(c.Request.RequestURI, recovery)
   120  			debug.PrintStack()
   121  		}
   122  	}
   123  }
   124  
   125  func ErrorLogger() ErrorHandlerFunc {
   126  	return func(recovery interface{}, c *gin.Context) {
   127  		for _, err := range c.Errors {
   128  			logger.Error(c.Request.RequestURI, err.Err)
   129  		}
   130  	}
   131  }