Adds bugsnag and newrelic metrics and error reporting

Configuration variables are added under the REGISTRY_REPORTING
namespace, for example REGISTRY_REPORTING_BUGSNAG_APIKEY
This commit is contained in:
Brian Bland 2014-12-12 17:49:06 -08:00
parent d726630ad0
commit 43a50b5e82
2 changed files with 82 additions and 1 deletions

View file

@ -11,6 +11,9 @@ import (
log "github.com/Sirupsen/logrus" log "github.com/Sirupsen/logrus"
"github.com/bugsnag/bugsnag-go"
"github.com/yvasiyarov/gorelic"
"github.com/docker/docker-registry" "github.com/docker/docker-registry"
"github.com/docker/docker-registry/configuration" "github.com/docker/docker-registry/configuration"
_ "github.com/docker/docker-registry/storagedriver/filesystem" _ "github.com/docker/docker-registry/storagedriver/filesystem"
@ -27,7 +30,8 @@ func main() {
} }
app := registry.NewApp(*config) 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.SetLevel(logLevel(config.Loglevel))
log.Infof("listening on %v", config.HTTP.Addr) log.Infof("listening on %v", config.HTTP.Addr)
@ -82,3 +86,39 @@ func logLevel(level configuration.Loglevel) log.Level {
return l 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
}

View file

@ -24,6 +24,9 @@ type Configuration struct {
// Storage is the configuration for the registry's storage driver // Storage is the configuration for the registry's storage driver
Storage Storage `yaml:"storage"` Storage Storage `yaml:"storage"`
// Reporting is the configuration for error reporting
Reporting Reporting `yaml:"reporting"`
// HTTP contains configuration parameters for the registry's http // HTTP contains configuration parameters for the registry's http
// interface. // interface.
HTTP struct { HTTP struct {
@ -180,6 +183,27 @@ func (storage Storage) MarshalYAML() (interface{}, error) {
// Parameters defines a key-value parameters mapping // Parameters defines a key-value parameters mapping
type Parameters map[string]string 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 // Parse parses an input configuration yaml document into a Configuration struct
// This should generally be capable of handling old configuration format versions // 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 return (*Configuration)(&config), nil
} }