diff --git a/cmd/tusd/cli/flags.go b/cmd/tusd/cli/flags.go index 1ffcfbf98..33e00db50 100644 --- a/cmd/tusd/cli/flags.go +++ b/cmd/tusd/cli/flags.go @@ -65,6 +65,7 @@ var Flags struct { PprofMutexProfileRate int BehindProxy bool VerboseOutput bool + LogFormat string S3TransferAcceleration bool TLSCertFile string TLSKeyFile string @@ -178,6 +179,7 @@ func ParseFlags() { f.BoolVar(&Flags.ShowGreeting, "show-greeting", true, "Show the greeting message") f.BoolVar(&Flags.ShowVersion, "version", false, "Print tusd version information") f.BoolVar(&Flags.VerboseOutput, "verbose", true, "Enable verbose logging output") + f.StringVar(&Flags.LogFormat, "log-format", "text", "Logging format (text or json)") }) fs.AddGroup("Timeout options", func(f *flag.FlagSet) { diff --git a/cmd/tusd/cli/log.go b/cmd/tusd/cli/log.go index 33dc30717..f21569c40 100644 --- a/cmd/tusd/cli/log.go +++ b/cmd/tusd/cli/log.go @@ -16,22 +16,38 @@ func SetupStructuredLogger() { level = slog.LevelDebug } - slogger := slog.New( - slog.NewTextHandler(logWriter{stdout}, &slog.HandlerOptions{ + replaceAttrFunc := func(groups []string, a slog.Attr) slog.Attr { + // Remove time attribute, because that is handled by the logger + if a.Key == slog.TimeKey { + return slog.Attr{} + } + // Rename `msg` to `event` + if a.Key == slog.MessageKey { + a.Key = "event" + } + return a + } + + var handler slog.Handler + switch Flags.LogFormat { + case "json": + handler = slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{ Level: level, - ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr { - // Remove time attribute, because that is handled by the logger - if a.Key == slog.TimeKey { - return slog.Attr{} - } - // Rename `msg` to `event` - if a.Key == slog.MessageKey { - a.Key = "event" - } - return a - }, - })) - slog.SetDefault(slogger) + }) + default: + handler = slog.NewTextHandler(logWriter{log.New(os.Stdout, "", log.LstdFlags|log.Lmicroseconds)}, &slog.HandlerOptions{ + Level: level, + ReplaceAttr: replaceAttrFunc, + }) + } + + slog.SetDefault(slog.New(handler)) + + if Flags.LogFormat == "json" { + // stdout and stderr helpers need to be overwritten to use slog + stdout = log.Default() + stderr = log.Default() + } } // logWriter is an io.Writer that forwards all input to the given log.Logger,