160 lines
4.9 KiB
Go
160 lines
4.9 KiB
Go
|
package bugsnag
|
||
|
|
||
|
import (
|
||
|
"log"
|
||
|
"net/http"
|
||
|
"path/filepath"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
// Configuration sets up and customizes communication with the Bugsnag API.
|
||
|
type Configuration struct {
|
||
|
// Your Bugsnag API key, e.g. "c9d60ae4c7e70c4b6c4ebd3e8056d2b8". You can
|
||
|
// find this by clicking Settings on https://bugsnag.com/.
|
||
|
APIKey string
|
||
|
// The Endpoint to notify about crashes. This defaults to
|
||
|
// "https://notify.bugsnag.com/", if you're using Bugsnag Enterprise then
|
||
|
// set it to your internal Bugsnag endpoint.
|
||
|
Endpoint string
|
||
|
|
||
|
// The current release stage. This defaults to "production" and is used to
|
||
|
// filter errors in the Bugsnag dashboard.
|
||
|
ReleaseStage string
|
||
|
// The currently running version of the app. This is used to filter errors
|
||
|
// in the Bugsnag dasboard. If you set this then Bugsnag will only re-open
|
||
|
// resolved errors if they happen in different app versions.
|
||
|
AppVersion string
|
||
|
// The hostname of the current server. This defaults to the return value of
|
||
|
// os.Hostname() and is graphed in the Bugsnag dashboard.
|
||
|
Hostname string
|
||
|
|
||
|
// The Release stages to notify in. If you set this then bugsnag-go will
|
||
|
// only send notifications to Bugsnag if the ReleaseStage is listed here.
|
||
|
NotifyReleaseStages []string
|
||
|
|
||
|
// packages that are part of your app. Bugsnag uses this to determine how
|
||
|
// to group errors and how to display them on your dashboard. You should
|
||
|
// include any packages that are part of your app, and exclude libraries
|
||
|
// and helpers. You can list wildcards here, and they'll be expanded using
|
||
|
// filepath.Glob. The default value is []string{"main*"}
|
||
|
ProjectPackages []string
|
||
|
|
||
|
// Any meta-data that matches these filters will be marked as [REDACTED]
|
||
|
// before sending a Notification to Bugsnag. It defaults to
|
||
|
// []string{"password", "secret"} so that request parameters like password,
|
||
|
// password_confirmation and auth_secret will not be sent to Bugsnag.
|
||
|
ParamsFilters []string
|
||
|
|
||
|
// The PanicHandler is used by Bugsnag to catch unhandled panics in your
|
||
|
// application. The default panicHandler uses mitchellh's panicwrap library,
|
||
|
// and you can disable this feature by passing an empty: func() {}
|
||
|
PanicHandler func()
|
||
|
|
||
|
// The logger that Bugsnag should log to. Uses the same defaults as go's
|
||
|
// builtin logging package. bugsnag-go logs whenever it notifies Bugsnag
|
||
|
// of an error, and when any error occurs inside the library itself.
|
||
|
Logger *log.Logger
|
||
|
// The http Transport to use, defaults to the default http Transport. This
|
||
|
// can be configured if you are in an environment like Google App Engine
|
||
|
// that has stringent conditions on making http requests.
|
||
|
Transport http.RoundTripper
|
||
|
// Whether bugsnag should notify synchronously. This defaults to false which
|
||
|
// causes bugsnag-go to spawn a new goroutine for each notification.
|
||
|
Synchronous bool
|
||
|
// TODO: remember to update the update() function when modifying this struct
|
||
|
}
|
||
|
|
||
|
func (config *Configuration) update(other *Configuration) *Configuration {
|
||
|
if other.APIKey != "" {
|
||
|
config.APIKey = other.APIKey
|
||
|
}
|
||
|
if other.Endpoint != "" {
|
||
|
config.Endpoint = other.Endpoint
|
||
|
}
|
||
|
if other.Hostname != "" {
|
||
|
config.Hostname = other.Hostname
|
||
|
}
|
||
|
if other.AppVersion != "" {
|
||
|
config.AppVersion = other.AppVersion
|
||
|
}
|
||
|
if other.ReleaseStage != "" {
|
||
|
config.ReleaseStage = other.ReleaseStage
|
||
|
}
|
||
|
if other.ParamsFilters != nil {
|
||
|
config.ParamsFilters = other.ParamsFilters
|
||
|
}
|
||
|
if other.ProjectPackages != nil {
|
||
|
config.ProjectPackages = other.ProjectPackages
|
||
|
}
|
||
|
if other.Logger != nil {
|
||
|
config.Logger = other.Logger
|
||
|
}
|
||
|
if other.NotifyReleaseStages != nil {
|
||
|
config.NotifyReleaseStages = other.NotifyReleaseStages
|
||
|
}
|
||
|
if other.PanicHandler != nil {
|
||
|
config.PanicHandler = other.PanicHandler
|
||
|
}
|
||
|
if other.Transport != nil {
|
||
|
config.Transport = other.Transport
|
||
|
}
|
||
|
if other.Synchronous {
|
||
|
config.Synchronous = true
|
||
|
}
|
||
|
|
||
|
return config
|
||
|
}
|
||
|
|
||
|
func (config *Configuration) merge(other *Configuration) *Configuration {
|
||
|
return config.clone().update(other)
|
||
|
}
|
||
|
|
||
|
func (config *Configuration) clone() *Configuration {
|
||
|
clone := *config
|
||
|
return &clone
|
||
|
}
|
||
|
|
||
|
func (config *Configuration) isProjectPackage(pkg string) bool {
|
||
|
for _, p := range config.ProjectPackages {
|
||
|
if match, _ := filepath.Match(p, pkg); match {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
func (config *Configuration) stripProjectPackages(file string) string {
|
||
|
for _, p := range config.ProjectPackages {
|
||
|
if len(p) > 2 && p[len(p)-2] == '/' && p[len(p)-1] == '*' {
|
||
|
p = p[:len(p)-1]
|
||
|
} else {
|
||
|
p = p + "/"
|
||
|
}
|
||
|
if strings.HasPrefix(file, p) {
|
||
|
return strings.TrimPrefix(file, p)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return file
|
||
|
}
|
||
|
|
||
|
func (config *Configuration) log(fmt string, args ...interface{}) {
|
||
|
if config != nil && config.Logger != nil {
|
||
|
config.Logger.Printf(fmt, args...)
|
||
|
} else {
|
||
|
log.Printf(fmt, args...)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (config *Configuration) notifyInReleaseStage() bool {
|
||
|
if config.NotifyReleaseStages == nil {
|
||
|
return true
|
||
|
}
|
||
|
for _, r := range config.NotifyReleaseStages {
|
||
|
if r == config.ReleaseStage {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
return false
|
||
|
}
|