diff --git a/cmd/registry/main.go b/cmd/registry/main.go index 29fa24c1..ba859eec 100644 --- a/cmd/registry/main.go +++ b/cmd/registry/main.go @@ -11,6 +11,9 @@ import ( log "github.com/Sirupsen/logrus" + "github.com/bugsnag/bugsnag-go" + "github.com/yvasiyarov/gorelic" + "github.com/docker/docker-registry" "github.com/docker/docker-registry/configuration" _ "github.com/docker/docker-registry/storagedriver/filesystem" @@ -27,7 +30,8 @@ func main() { } app := registry.NewApp(*config) - handler := handlers.CombinedLoggingHandler(os.Stdout, app) + handler := configureReporting(app) + handler = handlers.CombinedLoggingHandler(os.Stdout, handler) log.SetLevel(logLevel(config.Loglevel)) log.Infof("listening on %v", config.HTTP.Addr) @@ -82,3 +86,39 @@ func logLevel(level configuration.Loglevel) log.Level { return l } + +func configureReporting(app *registry.App) http.Handler { + var handler http.Handler = app + + if app.Config.Reporting.Bugsnag.APIKey != "" { + bugsnagConfig := bugsnag.Configuration{ + APIKey: app.Config.Reporting.Bugsnag.APIKey, + // TODO(brianbland): provide the registry version here + // AppVersion: "2.0", + } + if app.Config.Reporting.Bugsnag.ReleaseStage != "" { + bugsnagConfig.ReleaseStage = app.Config.Reporting.Bugsnag.ReleaseStage + } + if app.Config.Reporting.Bugsnag.Endpoint != "" { + bugsnagConfig.Endpoint = app.Config.Reporting.Bugsnag.Endpoint + } + bugsnag.Configure(bugsnagConfig) + + handler = bugsnag.Handler(handler) + } + + if app.Config.Reporting.NewRelic.LicenseKey != "" { + agent := gorelic.NewAgent() + agent.NewrelicLicense = app.Config.Reporting.NewRelic.LicenseKey + if app.Config.Reporting.NewRelic.Name != "" { + agent.NewrelicName = app.Config.Reporting.NewRelic.Name + } + agent.CollectHTTPStat = true + agent.Verbose = true + agent.Run() + + handler = agent.WrapHTTPHandler(handler) + } + + return handler +} diff --git a/configuration/configuration.go b/configuration/configuration.go index 2d7e476b..96d664f1 100644 --- a/configuration/configuration.go +++ b/configuration/configuration.go @@ -24,6 +24,9 @@ type Configuration struct { // Storage is the configuration for the registry's storage driver Storage Storage `yaml:"storage"` + // Reporting is the configuration for error reporting + Reporting Reporting `yaml:"reporting"` + // HTTP contains configuration parameters for the registry's http // interface. HTTP struct { @@ -180,6 +183,27 @@ func (storage Storage) MarshalYAML() (interface{}, error) { // Parameters defines a key-value parameters mapping type Parameters map[string]string +// Reporting defines error reporting methods. +type Reporting struct { + // Bugsnag configures error reporting for Bugsnag (bugsnag.com). + Bugsnag struct { + // APIKey is the Bugsnag api key. + APIKey string `yaml:"apikey"` + // ReleaseStage tracks where the registry is deployed. + // Examples: production, staging, development + ReleaseStage string `yaml:"releasestage"` + // Endpoint is used for specifying an enterprise Bugsnag endpoint. + Endpoint string `yaml:"endpoint"` + } `yaml:"bugsnag"` + // NewRelic configures error reporting for NewRelic (newrelic.com) + NewRelic struct { + // LicenseKey is the NewRelic user license key + LicenseKey string `yaml:"licensekey"` + // AppName is the component name of the registry in NewRelic + Name string `yaml:"name"` + } `yaml:"newrelic"` +} + // Parse parses an input configuration yaml document into a Configuration struct // This should generally be capable of handling old configuration format versions // @@ -264,6 +288,23 @@ func parseV0_1Registry(in []byte) (*Configuration, error) { } } + if bugsnagAPIKey, ok := envMap["REGISTRY_REPORTING_BUGSNAG_APIKEY"]; ok { + config.Reporting.Bugsnag.APIKey = bugsnagAPIKey + } + if bugsnagReleaseStage, ok := envMap["REGISTRY_REPORTING_BUGSNAG_RELEASESTAGE"]; ok { + config.Reporting.Bugsnag.ReleaseStage = bugsnagReleaseStage + } + if bugsnagEndpoint, ok := envMap["REGISTRY_REPORTING_BUGSNAG_ENDPOINT"]; ok { + config.Reporting.Bugsnag.Endpoint = bugsnagEndpoint + } + + if newRelicLicenseKey, ok := envMap["REGISTRY_REPORTING_NEWRELIC_LICENSEKEY"]; ok { + config.Reporting.NewRelic.LicenseKey = newRelicLicenseKey + } + if newRelicName, ok := envMap["REGISTRY_REPORTING_NEWRELIC_NAME"]; ok { + config.Reporting.NewRelic.Name = newRelicName + } + return (*Configuration)(&config), nil }