bugsnag.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. package bugsnag
  2. import (
  3. "github.com/bugsnag/bugsnag-go/errors"
  4. "log"
  5. "net/http"
  6. "os"
  7. "path/filepath"
  8. "runtime"
  9. "sync"
  10. // Fixes a bug with SHA-384 intermediate certs on some platforms.
  11. // - https://github.com/bugsnag/bugsnag-go/issues/9
  12. _ "crypto/sha512"
  13. )
  14. // The current version of bugsnag-go.
  15. const VERSION = "1.3.2"
  16. var once sync.Once
  17. var middleware middlewareStack
  18. // The configuration for the default bugsnag notifier.
  19. var Config Configuration
  20. var defaultNotifier = Notifier{&Config, nil}
  21. // Configure Bugsnag. The only required setting is the APIKey, which can be
  22. // obtained by clicking on "Settings" in your Bugsnag dashboard. This function
  23. // is also responsible for installing the global panic handler, so it should be
  24. // called as early as possible in your initialization process.
  25. func Configure(config Configuration) {
  26. Config.update(&config)
  27. once.Do(Config.PanicHandler)
  28. }
  29. // Notify sends an error to Bugsnag along with the current stack trace. The
  30. // rawData is used to send extra information along with the error. For example
  31. // you can pass the current http.Request to Bugsnag to see information about it
  32. // in the dashboard, or set the severity of the notification.
  33. func Notify(err error, rawData ...interface{}) error {
  34. return defaultNotifier.Notify(errors.New(err, 1), rawData...)
  35. }
  36. // AutoNotify logs a panic on a goroutine and then repanics.
  37. // It should only be used in places that have existing panic handlers further
  38. // up the stack. The rawData is used to send extra information along with any
  39. // panics that are handled this way.
  40. // Usage:
  41. // go func() {
  42. // defer bugsnag.AutoNotify()
  43. // // (possibly crashy code)
  44. // }()
  45. // See also: bugsnag.Recover()
  46. func AutoNotify(rawData ...interface{}) {
  47. if err := recover(); err != nil {
  48. severity := defaultNotifier.getDefaultSeverity(rawData, SeverityError)
  49. state := HandledState{SeverityReasonHandledPanic, severity, true, ""}
  50. rawData = append([]interface{}{state}, rawData...)
  51. defaultNotifier.NotifySync(errors.New(err, 2), true, rawData...)
  52. panic(err)
  53. }
  54. }
  55. // Recover logs a panic on a goroutine and then recovers.
  56. // The rawData is used to send extra information along with
  57. // any panics that are handled this way
  58. // Usage: defer bugsnag.Recover()
  59. func Recover(rawData ...interface{}) {
  60. if err := recover(); err != nil {
  61. severity := defaultNotifier.getDefaultSeverity(rawData, SeverityWarning)
  62. state := HandledState{SeverityReasonHandledPanic, severity, false, ""}
  63. rawData = append([]interface{}{state}, rawData...)
  64. defaultNotifier.Notify(errors.New(err, 2), rawData...)
  65. }
  66. }
  67. // OnBeforeNotify adds a callback to be run before a notification is sent to
  68. // Bugsnag. It can be used to modify the event or its MetaData. Changes made
  69. // to the configuration are local to notifying about this event. To prevent the
  70. // event from being sent to Bugsnag return an error, this error will be
  71. // returned from bugsnag.Notify() and the event will not be sent.
  72. func OnBeforeNotify(callback func(event *Event, config *Configuration) error) {
  73. middleware.OnBeforeNotify(callback)
  74. }
  75. // Handler creates an http Handler that notifies Bugsnag any panics that
  76. // happen. It then repanics so that the default http Server panic handler can
  77. // handle the panic too. The rawData is used to send extra information along
  78. // with any panics that are handled this way.
  79. func Handler(h http.Handler, rawData ...interface{}) http.Handler {
  80. notifier := New(rawData...)
  81. if h == nil {
  82. h = http.DefaultServeMux
  83. }
  84. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  85. defer notifier.AutoNotify(r)
  86. h.ServeHTTP(w, r)
  87. })
  88. }
  89. // HandlerFunc creates an http HandlerFunc that notifies Bugsnag about any
  90. // panics that happen. It then repanics so that the default http Server panic
  91. // handler can handle the panic too. The rawData is used to send extra
  92. // information along with any panics that are handled this way. If you have
  93. // already wrapped your http server using bugsnag.Handler() you don't also need
  94. // to wrap each HandlerFunc.
  95. func HandlerFunc(h http.HandlerFunc, rawData ...interface{}) http.HandlerFunc {
  96. notifier := New(rawData...)
  97. return func(w http.ResponseWriter, r *http.Request) {
  98. defer notifier.AutoNotify(r)
  99. h(w, r)
  100. }
  101. }
  102. func init() {
  103. // Set up builtin middlewarez
  104. OnBeforeNotify(httpRequestMiddleware)
  105. // Default configuration
  106. sourceRoot := ""
  107. if gopath := os.Getenv("GOPATH"); len(gopath) > 0 {
  108. sourceRoot = filepath.Join(gopath, "src") + "/"
  109. } else {
  110. sourceRoot = filepath.Join(runtime.GOROOT(), "src") + "/"
  111. }
  112. Config.update(&Configuration{
  113. APIKey: "",
  114. Endpoint: "https://notify.bugsnag.com/",
  115. Hostname: "",
  116. AppType: "",
  117. AppVersion: "",
  118. ReleaseStage: "",
  119. ParamsFilters: []string{"password", "secret"},
  120. SourceRoot: sourceRoot,
  121. // * for app-engine
  122. ProjectPackages: []string{"main*"},
  123. NotifyReleaseStages: nil,
  124. Logger: log.New(os.Stdout, log.Prefix(), log.Flags()),
  125. PanicHandler: defaultPanicHandler,
  126. Transport: http.DefaultTransport,
  127. })
  128. hostname, err := os.Hostname()
  129. if err == nil {
  130. Config.Hostname = hostname
  131. }
  132. }