Skip to content

Commit a08abec

Browse files
committed
Update dockerd to support JSON logging format
Update docker to support a '--log-format' option, which accepts either 'text' (default) or 'json'. Propagate the log format to containerd as well, to ensure that everything will be logged consistently. Signed-off-by: Philip K. Warren <[email protected]>
1 parent d2452c2 commit a08abec

5 files changed

Lines changed: 71 additions & 5 deletions

File tree

cmd/dockerd/daemon.go

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,7 @@ func loadDaemonCliConfig(opts *daemonOptions) (*config.Config, error) {
478478
conf.Debug = opts.Debug
479479
conf.Hosts = opts.Hosts
480480
conf.LogLevel = opts.LogLevel
481+
conf.LogFormat = opts.LogFormat
481482

482483
if flags.Changed(FlagTLS) {
483484
conf.TLS = &opts.TLS
@@ -657,6 +658,10 @@ func (cli *DaemonCli) getContainerdDaemonOpts() ([]supervisor.DaemonOpt, error)
657658
opts = append(opts, supervisor.WithLogLevel(cli.LogLevel))
658659
}
659660

661+
if logFormat := cli.Config.LogFormat; logFormat != "" {
662+
opts = append(opts, supervisor.WithLogFormat(logFormat))
663+
}
664+
660665
if !cli.CriContainerd {
661666
// CRI support in the managed daemon is currently opt-in.
662667
//
@@ -867,11 +872,26 @@ func configureDaemonLogs(conf *config.Config) {
867872
} else {
868873
logrus.SetLevel(logrus.InfoLevel)
869874
}
870-
logrus.SetFormatter(&logrus.TextFormatter{
871-
TimestampFormat: jsonmessage.RFC3339NanoFixed,
872-
DisableColors: conf.RawLogs,
873-
FullTimestamp: true,
874-
})
875+
logFormat := conf.LogFormat
876+
if logFormat == "" {
877+
logFormat = log.TextFormat
878+
}
879+
var formatter logrus.Formatter
880+
switch logFormat {
881+
case log.JSONFormat:
882+
formatter = &logrus.JSONFormatter{
883+
TimestampFormat: jsonmessage.RFC3339NanoFixed,
884+
}
885+
case log.TextFormat:
886+
formatter = &logrus.TextFormatter{
887+
TimestampFormat: jsonmessage.RFC3339NanoFixed,
888+
DisableColors: conf.RawLogs,
889+
FullTimestamp: true,
890+
}
891+
default:
892+
panic("unsupported log format " + logFormat)
893+
}
894+
logrus.SetFormatter(formatter)
875895
}
876896

877897
func configureProxyEnv(conf *config.Config) {

cmd/dockerd/daemon_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package main
33
import (
44
"testing"
55

6+
"github.com/containerd/containerd/log"
67
"github.com/docker/docker/daemon/config"
78
"github.com/sirupsen/logrus"
89
"github.com/spf13/pflag"
@@ -155,6 +156,26 @@ func TestLoadDaemonCliConfigWithLogLevel(t *testing.T) {
155156
assert.Check(t, is.Equal("warn", loadedConfig.LogLevel))
156157
}
157158

159+
func TestLoadDaemonCliConfigWithLogFormat(t *testing.T) {
160+
tempFile := fs.NewFile(t, "config", fs.WithContent(`{"log-format": "json"}`))
161+
defer tempFile.Remove()
162+
163+
opts := defaultOptions(t, tempFile.Path())
164+
loadedConfig, err := loadDaemonCliConfig(opts)
165+
assert.NilError(t, err)
166+
assert.Assert(t, loadedConfig != nil)
167+
assert.Check(t, is.Equal(log.JSONFormat, loadedConfig.LogFormat))
168+
}
169+
170+
func TestLoadDaemonCliConfigWithInvalidLogFormat(t *testing.T) {
171+
tempFile := fs.NewFile(t, "config", fs.WithContent(`{"log-format": "foo"}`))
172+
defer tempFile.Remove()
173+
174+
opts := defaultOptions(t, tempFile.Path())
175+
_, err := loadDaemonCliConfig(opts)
176+
assert.Check(t, is.ErrorContains(err, "invalid log format: foo"))
177+
}
178+
158179
func TestLoadDaemonConfigWithEmbeddedOptions(t *testing.T) {
159180
content := `{"tlscacert": "/etc/certs/ca.pem", "log-driver": "syslog"}`
160181
tempFile := fs.NewFile(t, "config", fs.WithContent(content))

cmd/dockerd/options.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package main
22

33
import (
4+
"fmt"
45
"os"
56
"path/filepath"
67

8+
"github.com/containerd/containerd/log"
79
"github.com/docker/docker/daemon/config"
810
"github.com/docker/docker/opts"
911
"github.com/docker/docker/pkg/homedir"
@@ -72,6 +74,7 @@ type daemonOptions struct {
7274
Debug bool
7375
Hosts []string
7476
LogLevel string
77+
LogFormat string
7578
TLS bool
7679
TLSVerify bool
7780
TLSOptions *tlsconfig.Options
@@ -104,6 +107,8 @@ func (o *daemonOptions) installFlags(flags *pflag.FlagSet) {
104107
flags.BoolVarP(&o.Debug, "debug", "D", false, "Enable debug mode")
105108
flags.BoolVar(&o.Validate, "validate", false, "Validate daemon configuration and exit")
106109
flags.StringVarP(&o.LogLevel, "log-level", "l", "info", `Set the logging level ("debug"|"info"|"warn"|"error"|"fatal")`)
110+
flags.StringVar(&o.LogFormat, "log-format", log.TextFormat,
111+
fmt.Sprintf(`Set the logging format ("%s"|"%s")`, log.TextFormat, log.JSONFormat))
107112
flags.BoolVar(&o.TLS, FlagTLS, DefaultTLSValue, "Use TLS; implied by --tlsverify")
108113
flags.BoolVar(&o.TLSVerify, FlagTLSVerify, dockerTLSVerify || DefaultTLSValue, "Use TLS and verify the remote")
109114

daemon/config/config.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ type CommonConfig struct {
187187
Debug bool `json:"debug,omitempty"`
188188
Hosts []string `json:"hosts,omitempty"`
189189
LogLevel string `json:"log-level,omitempty"`
190+
LogFormat string `json:"log-format,omitempty"`
190191
TLS *bool `json:"tls,omitempty"`
191192
TLSVerify *bool `json:"tlsverify,omitempty"`
192193

@@ -594,6 +595,16 @@ func Validate(config *Config) error {
594595
}
595596
}
596597

598+
// validate log-format
599+
if logFormat := config.LogFormat; logFormat != "" {
600+
switch logFormat {
601+
case log.TextFormat, log.JSONFormat:
602+
// These are valid
603+
default:
604+
return errors.Errorf("invalid log format: %s", logFormat)
605+
}
606+
}
607+
597608
// validate DNS
598609
for _, dns := range config.DNS {
599610
if _, err := opts.ValidateIPAddress(dns); err != nil {

libcontainerd/supervisor/remote_daemon_options.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,15 @@ func WithLogLevel(lvl string) DaemonOpt {
1313
}
1414
}
1515

16+
// WithLogFormat defines the containerd log format.
17+
// This only makes sense if WithStartDaemon() was set to true.
18+
func WithLogFormat(format string) DaemonOpt {
19+
return func(r *remote) error {
20+
r.Debug.Format = format
21+
return nil
22+
}
23+
}
24+
1625
// WithCRIDisabled disables the CRI plugin.
1726
func WithCRIDisabled() DaemonOpt {
1827
return func(r *remote) error {

0 commit comments

Comments
 (0)