diff --git a/cmd/registry/config.yml b/cmd/registry/config.yml index bb3ade118..a73644f0c 100644 --- a/cmd/registry/config.yml +++ b/cmd/registry/config.yml @@ -1,5 +1,6 @@ version: 0.1 -loglevel: debug +log: + level: debug storage: filesystem: rootdirectory: /tmp/registry-dev diff --git a/cmd/registry/main.go b/cmd/registry/main.go index 6c4428950..eb71267e9 100644 --- a/cmd/registry/main.go +++ b/cmd/registry/main.go @@ -9,6 +9,7 @@ import ( "os" log "github.com/Sirupsen/logrus" + "github.com/Sirupsen/logrus/formatters/logstash" "github.com/bugsnag/bugsnag-go" "github.com/docker/distribution/configuration" ctxu "github.com/docker/distribution/context" @@ -49,7 +50,10 @@ func main() { fatalf("configuration error: %v", err) } - log.SetLevel(logLevel(config.Loglevel)) + if err := configureLogging(config); err != nil { + fatalf("error configuring logger: %v", err) + } + ctx = context.WithValue(ctx, "version", version.Version) ctx = ctxu.WithLogger(ctx, ctxu.GetLogger(ctx, "version")) @@ -111,16 +115,6 @@ func resolveConfiguration() (*configuration.Configuration, error) { return config, nil } -func logLevel(level configuration.Loglevel) log.Level { - l, err := log.ParseLevel(string(level)) - if err != nil { - log.Warnf("error parsing level %q: %v", level, err) - l = log.InfoLevel - } - - return l -} - func configureReporting(app *handlers.App) http.Handler { var handler http.Handler = app @@ -157,6 +151,48 @@ func configureReporting(app *handlers.App) http.Handler { return handler } +// configureLogging the default logger using the configuration. Must be called +// before creating any contextual loggers. +func configureLogging(config *configuration.Configuration) error { + if config.Log.Level == "" && config.Log.Formatter == "" { + // If no config for logging is set, fallback to deprecated "Loglevel". + log.SetLevel(logLevel(config.Loglevel)) + return nil + } + + log.SetLevel(logLevel(config.Log.Level)) + + switch config.Log.Formatter { + case "json": + log.SetFormatter(&log.JSONFormatter{}) + case "text": + log.SetFormatter(&log.TextFormatter{}) + case "logstash": + log.SetFormatter(&logstash.LogstashFormatter{Type: "registry"}) + default: + // just let the library use default on empty string. + if config.Log.Formatter != "" { + return fmt.Errorf("unsupported logging formatter: %q", config.Log.Formatter) + } + } + + if config.Log.Formatter != "" { + log.Debugf("using %q logging formatter", config.Log.Formatter) + } + + return nil +} + +func logLevel(level configuration.Loglevel) log.Level { + l, err := log.ParseLevel(string(level)) + if err != nil { + l = log.InfoLevel + log.Warnf("error parsing level %q: %v, using %q ", level, err, l) + } + + return l +} + // debugServer starts the debug server with pprof, expvar among other // endpoints. The addr should not be exposed externally. For most of these to // work, tls cannot be enabled on the endpoint, so it is generally separate. diff --git a/configuration/configuration.go b/configuration/configuration.go index 6c03b27fa..c5bb035fe 100644 --- a/configuration/configuration.go +++ b/configuration/configuration.go @@ -16,7 +16,19 @@ type Configuration struct { // Version is the version which defines the format of the rest of the configuration Version Version `yaml:"version"` - // Loglevel is the level at which registry operations are logged + // Log supports setting various parameters related to the logging + // subsystem. + Log struct { + // Level is the granularity at which registry operations are logged. + Level Loglevel `yaml:"level"` + + // Formatter overrides the default formatter with another. Options + // include "text", "json" and "logstash". + Formatter string `yaml:"formatter"` + } + + // Loglevel is the level at which registry operations are logged. This is + // deprecated. Please use Log.Level in the future. Loglevel Loglevel `yaml:"loglevel"` // Storage is the configuration for the registry's storage driver diff --git a/doc/configuration.md b/doc/configuration.md index 9441116b0..32c28c583 100644 --- a/doc/configuration.md +++ b/doc/configuration.md @@ -4,7 +4,10 @@ Below is a comprehensive example of all possible configuration options for the r ```yaml version: 0.1 -loglevel: debug +log: + level: debug + formatter: text +loglevel: debug # deprecated: use "log" storage: filesystem: rootdirectory: /tmp/registry @@ -87,18 +90,34 @@ The version option is **required** and indicates the version of the configuratio N.B. The version of the registry software may be found at [/version/version.go](https://github.com/docker/distribution/blob/master/version/version.go) +## log + +The log subsection configures the behavior of the logging system. The logging +system outputs everything to stdout. The granularity and format of the log +messages can be adjusted with this configuration section. + +```yaml +log: + level: debug + formatter: text +``` + +- level: **Optional** - Sets the sensitivity of logging output. Permitted + values are `error`, `warn`, `info` and `debug`. The default is `info`. +- formatter: **Optional** - This selects the format of logging output, which + mostly affects how keyed attributes for a log line are encoded. Options are + "text", "json" or "logstash". The default is "text". + ## loglevel +> **DEPRECATED:** Please use [log](#log) instead. + ```yaml loglevel: debug ``` -The loglevel option is **required** and sets the sensitivity of logging output. Permitted values are: - -- ```error``` -- ```warn``` -- ```info``` -- ```debug``` +Permitted values are `error`, `warn`, `info` and `debug`. The default is +`info`. ## storage