diff --git a/cmd/compose/logs.go b/cmd/compose/logs.go index 4f54acf23a4..b89b6dec38e 100644 --- a/cmd/compose/logs.go +++ b/cmd/compose/logs.go @@ -20,10 +20,9 @@ import ( "context" "os" - "github.com/docker/compose/v2/cmd/formatter" - "github.com/spf13/cobra" + "github.com/docker/compose/v2/cmd/formatter" "github.com/docker/compose/v2/pkg/api" ) @@ -67,7 +66,7 @@ func runLogs(ctx context.Context, backend api.Service, opts logsOptions, service if err != nil { return err } - consumer := formatter.NewLogConsumer(ctx, os.Stdout, os.Stderr, !opts.noColor, !opts.noPrefix) + consumer := formatter.NewLogConsumer(ctx, os.Stdout, os.Stderr, !opts.noColor, !opts.noPrefix, false) return backend.Logs(ctx, name, consumer, api.LogOptions{ Project: project, Services: services, diff --git a/cmd/compose/up.go b/cmd/compose/up.go index eae6b3d1511..3d35c7238da 100644 --- a/cmd/compose/up.go +++ b/cmd/compose/up.go @@ -49,6 +49,7 @@ type upOptions struct { noPrefix bool attachDependencies bool attach []string + timestamp bool wait bool } @@ -126,6 +127,7 @@ func upCommand(p *projectOptions, backend api.Service) *cobra.Command { flags.BoolVar(&up.cascadeStop, "abort-on-container-exit", false, "Stops all containers if any container was stopped. Incompatible with -d") flags.StringVar(&up.exitCodeFrom, "exit-code-from", "", "Return the exit code of the selected service container. Implies --abort-on-container-exit") flags.IntVarP(&create.timeout, "timeout", "t", 10, "Use this timeout in seconds for container shutdown when attached or when containers are already running.") + flags.BoolVar(&up.timestamp, "timestamp", false, "Show timestamps.") flags.BoolVar(&up.noDeps, "no-deps", false, "Don't start linked services.") flags.BoolVar(&create.recreateDeps, "always-recreate-deps", false, "Recreate dependent containers. Incompatible with --no-recreate.") flags.BoolVarP(&create.noInherit, "renew-anon-volumes", "V", false, "Recreate anonymous volumes instead of retrieving data from the previous containers.") @@ -176,7 +178,7 @@ func runUp(ctx context.Context, backend api.Service, createOptions createOptions var consumer api.LogConsumer if !upOptions.Detach { - consumer = formatter.NewLogConsumer(ctx, os.Stdout, os.Stderr, !upOptions.noColor, !upOptions.noPrefix) + consumer = formatter.NewLogConsumer(ctx, os.Stdout, os.Stderr, !upOptions.noColor, !upOptions.noPrefix, upOptions.timestamp) } attachTo := services diff --git a/cmd/formatter/logs.go b/cmd/formatter/logs.go index 715a9ddaf98..836c877d291 100644 --- a/cmd/formatter/logs.go +++ b/cmd/formatter/logs.go @@ -23,8 +23,10 @@ import ( "strconv" "strings" "sync" + "time" "github.com/docker/compose/v2/pkg/api" + "github.com/docker/docker/pkg/jsonmessage" ) // LogConsumer consume logs from services and format them @@ -36,10 +38,11 @@ type logConsumer struct { stderr io.Writer color bool prefix bool + timestamp bool } // NewLogConsumer creates a new LogConsumer -func NewLogConsumer(ctx context.Context, stdout, stderr io.Writer, color bool, prefix bool) api.LogConsumer { +func NewLogConsumer(ctx context.Context, stdout, stderr io.Writer, color, prefix, timestamp bool) api.LogConsumer { return &logConsumer{ ctx: ctx, presenters: sync.Map{}, @@ -48,6 +51,7 @@ func NewLogConsumer(ctx context.Context, stdout, stderr io.Writer, color bool, p stderr: stderr, color: color, prefix: prefix, + timestamp: timestamp, } } @@ -99,8 +103,13 @@ func (l *logConsumer) write(w io.Writer, container, message string) { return } p := l.getPresenter(container) + timestanp := time.Now().Format(jsonmessage.RFC3339NanoFixed) for _, line := range strings.Split(message, "\n") { - fmt.Fprintf(w, "%s%s\n", p.prefix, line) + if l.timestamp { + fmt.Fprintf(w, "%s%s%s\n", p.prefix, timestanp, line) + } else { + fmt.Fprintf(w, "%s%s\n", p.prefix, line) + } } } diff --git a/docs/reference/compose_up.md b/docs/reference/compose_up.md index 2a883c530fd..4e226d6708a 100644 --- a/docs/reference/compose_up.md +++ b/docs/reference/compose_up.md @@ -27,6 +27,7 @@ Create and start containers | `-V`, `--renew-anon-volumes` | | | Recreate anonymous volumes instead of retrieving data from the previous containers. | | `--scale` | `stringArray` | | Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present. | | `-t`, `--timeout` | `int` | `10` | Use this timeout in seconds for container shutdown when attached or when containers are already running. | +| `--timestamp` | | | Show timestamps. | | `--wait` | | | Wait for services to be running\|healthy. Implies detached mode. | diff --git a/docs/reference/docker_compose_up.yaml b/docs/reference/docker_compose_up.yaml index cbcc4c5881f..364567f1f04 100644 --- a/docs/reference/docker_compose_up.yaml +++ b/docs/reference/docker_compose_up.yaml @@ -230,6 +230,16 @@ options: experimentalcli: false kubernetes: false swarm: false + - option: timestamp + value_type: bool + default_value: "false" + description: Show timestamps. + deprecated: false + hidden: false + experimental: false + experimentalcli: false + kubernetes: false + swarm: false - option: wait value_type: bool default_value: "false"