82 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Go
		
	
	
			
		
		
	
	
			82 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Go
		
	
	
package logrus_bugsnag
 | 
						|
 | 
						|
import (
 | 
						|
	"errors"
 | 
						|
 | 
						|
	"github.com/sirupsen/logrus"
 | 
						|
	"github.com/bugsnag/bugsnag-go"
 | 
						|
	bugsnag_errors "github.com/bugsnag/bugsnag-go/errors"
 | 
						|
)
 | 
						|
 | 
						|
type bugsnagHook struct{}
 | 
						|
 | 
						|
// ErrBugsnagUnconfigured is returned if NewBugsnagHook is called before
 | 
						|
// bugsnag.Configure. Bugsnag must be configured before the hook.
 | 
						|
var ErrBugsnagUnconfigured = errors.New("bugsnag must be configured before installing this logrus hook")
 | 
						|
 | 
						|
// ErrBugsnagSendFailed indicates that the hook failed to submit an error to
 | 
						|
// bugsnag. The error was successfully generated, but `bugsnag.Notify()`
 | 
						|
// failed.
 | 
						|
type ErrBugsnagSendFailed struct {
 | 
						|
	err error
 | 
						|
}
 | 
						|
 | 
						|
func (e ErrBugsnagSendFailed) Error() string {
 | 
						|
	return "failed to send error to Bugsnag: " + e.err.Error()
 | 
						|
}
 | 
						|
 | 
						|
// NewBugsnagHook initializes a logrus hook which sends exceptions to an
 | 
						|
// exception-tracking service compatible with the Bugsnag API. Before using
 | 
						|
// this hook, you must call bugsnag.Configure(). The returned object should be
 | 
						|
// registered with a log via `AddHook()`
 | 
						|
//
 | 
						|
// Entries that trigger an Error, Fatal or Panic should now include an "error"
 | 
						|
// field to send to Bugsnag.
 | 
						|
func NewBugsnagHook() (*bugsnagHook, error) {
 | 
						|
	if bugsnag.Config.APIKey == "" {
 | 
						|
		return nil, ErrBugsnagUnconfigured
 | 
						|
	}
 | 
						|
	return &bugsnagHook{}, nil
 | 
						|
}
 | 
						|
 | 
						|
// skipStackFrames skips logrus stack frames before logging to Bugsnag.
 | 
						|
const skipStackFrames = 4
 | 
						|
 | 
						|
// Fire forwards an error to Bugsnag. Given a logrus.Entry, it extracts the
 | 
						|
// "error" field (or the Message if the error isn't present) and sends it off.
 | 
						|
func (hook *bugsnagHook) Fire(entry *logrus.Entry) error {
 | 
						|
	var notifyErr error
 | 
						|
	err, ok := entry.Data["error"].(error)
 | 
						|
	if ok {
 | 
						|
		notifyErr = err
 | 
						|
	} else {
 | 
						|
		notifyErr = errors.New(entry.Message)
 | 
						|
	}
 | 
						|
 | 
						|
	metadata := bugsnag.MetaData{}
 | 
						|
	metadata["metadata"] = make(map[string]interface{})
 | 
						|
	for key, val := range entry.Data {
 | 
						|
		if key != "error" {
 | 
						|
			metadata["metadata"][key] = val
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	errWithStack := bugsnag_errors.New(notifyErr, skipStackFrames)
 | 
						|
	bugsnagErr := bugsnag.Notify(errWithStack, metadata)
 | 
						|
	if bugsnagErr != nil {
 | 
						|
		return ErrBugsnagSendFailed{bugsnagErr}
 | 
						|
	}
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// Levels enumerates the log levels on which the error should be forwarded to
 | 
						|
// bugsnag: everything at or above the "Error" level.
 | 
						|
func (hook *bugsnagHook) Levels() []logrus.Level {
 | 
						|
	return []logrus.Level{
 | 
						|
		logrus.ErrorLevel,
 | 
						|
		logrus.FatalLevel,
 | 
						|
		logrus.PanicLevel,
 | 
						|
	}
 | 
						|
}
 |