From dcbe5b1182b2d1a87f137515035d281fa5a93e96 Mon Sep 17 00:00:00 2001 From: Jamie Hannaford Date: Wed, 10 May 2017 14:00:00 +0200 Subject: [PATCH 1/3] Add new CLI option for --until Signed-off-by: Jamie Hannaford Upstream-commit: 6f309316e28922c7671dcf5a490f0546f8e062be Component: cli --- components/cli/cli/command/container/logs.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/cli/cli/command/container/logs.go b/components/cli/cli/command/container/logs.go index 6bf849f212..d8a7650074 100644 --- a/components/cli/cli/command/container/logs.go +++ b/components/cli/cli/command/container/logs.go @@ -14,6 +14,7 @@ import ( type logsOptions struct { follow bool since string + until string timestamps bool details bool tail string @@ -38,6 +39,8 @@ func NewLogsCommand(dockerCli command.Cli) *cobra.Command { flags := cmd.Flags() flags.BoolVarP(&opts.follow, "follow", "f", false, "Follow log output") flags.StringVar(&opts.since, "since", "", "Show logs since timestamp (e.g. 2013-01-02T13:23:37) or relative (e.g. 42m for 42 minutes)") + flags.StringVar(&opts.until, "until", "", "Show logs before a timestamp (e.g. 2013-01-02T13:23:37) or relative (e.g. 42m for 42 minutes)") + flags.SetAnnotation("until", "version", []string{"1.35"}) flags.BoolVarP(&opts.timestamps, "timestamps", "t", false, "Show timestamps") flags.BoolVar(&opts.details, "details", false, "Show extra details provided to logs") flags.StringVar(&opts.tail, "tail", "all", "Number of lines to show from the end of the logs") @@ -51,6 +54,7 @@ func runLogs(dockerCli command.Cli, opts *logsOptions) error { ShowStdout: true, ShowStderr: true, Since: opts.since, + Until: opts.until, Timestamps: opts.timestamps, Follow: opts.follow, Tail: opts.tail, From e18edc6a6b9e4e45b29c034df6eff3e6d68b2165 Mon Sep 17 00:00:00 2001 From: Jamie Hannaford Date: Mon, 13 Nov 2017 10:53:13 +0100 Subject: [PATCH 2/3] add test for logs Signed-off-by: Jamie Hannaford Upstream-commit: 9c9303e11350cc58078c1fcc59cd1ef1b4b0ed88 Component: cli --- .../cli/cli/command/container/client_test.go | 8 +++ .../cli/cli/command/container/logs_test.go | 62 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 components/cli/cli/command/container/logs_test.go diff --git a/components/cli/cli/command/container/client_test.go b/components/cli/cli/command/container/client_test.go index 9a17875c2d..692ed3115a 100644 --- a/components/cli/cli/command/container/client_test.go +++ b/components/cli/cli/command/container/client_test.go @@ -20,6 +20,7 @@ type fakeClient struct { infoFunc func() (types.Info, error) containerStatPathFunc func(container, path string) (types.ContainerPathStat, error) containerCopyFromFunc func(container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) + logFunc func(string, types.ContainerLogsOptions) (io.ReadCloser, error) } func (f *fakeClient) ContainerInspect(_ context.Context, containerID string) (types.ContainerJSON, error) { @@ -87,3 +88,10 @@ func (f *fakeClient) CopyFromContainer(_ context.Context, container, srcPath str } return nil, types.ContainerPathStat{}, nil } + +func (f *fakeClient) ContainerLogs(_ context.Context, container string, options types.ContainerLogsOptions) (io.ReadCloser, error) { + if f.logFunc != nil { + return f.logFunc(container, options) + } + return nil, nil +} diff --git a/components/cli/cli/command/container/logs_test.go b/components/cli/cli/command/container/logs_test.go new file mode 100644 index 0000000000..592989da4d --- /dev/null +++ b/components/cli/cli/command/container/logs_test.go @@ -0,0 +1,62 @@ +package container + +import ( + "io" + "io/ioutil" + "strings" + "testing" + + "github.com/docker/cli/internal/test" + "github.com/docker/cli/internal/test/testutil" + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" + "github.com/stretchr/testify/assert" +) + +func TestRunLogs(t *testing.T) { + inspectFn := func(containerID string) (types.ContainerJSON, error) { + return types.ContainerJSON{ + Config: &container.Config{Tty: true}, + ContainerJSONBase: &types.ContainerJSONBase{State: &types.ContainerState{Running: false}}, + }, nil + } + + logFn := func(expectedOut string) func(string, types.ContainerLogsOptions) (io.ReadCloser, error) { + return func(container string, opts types.ContainerLogsOptions) (io.ReadCloser, error) { + return ioutil.NopCloser(strings.NewReader(expectedOut)), nil + } + } + + var testcases = []struct { + doc string + options *logsOptions + client fakeClient + expectedError string + expectedOut string + expectedErr string + }{ + { + doc: "successful logs", + expectedOut: "foo", + options: &logsOptions{}, + client: fakeClient{logFunc: logFn("foo"), inspectFunc: inspectFn}, + }, + } + + for _, testcase := range testcases { + t.Run(testcase.doc, func(t *testing.T) { + cli := test.NewFakeCli(&testcase.client) + + err := runLogs(cli, testcase.options) + if testcase.expectedError != "" { + testutil.ErrorContains(t, err, testcase.expectedError) + } else { + if !assert.NoError(t, err) { + return + } + } + assert.Equal(t, testcase.expectedOut, cli.OutBuffer().String()) + assert.Equal(t, testcase.expectedErr, cli.ErrBuffer().String()) + }) + } +} From e9b472f2e145e387c14e3de799b32031da4ed573 Mon Sep 17 00:00:00 2001 From: Jamie Hannaford Date: Tue, 14 Nov 2017 16:43:35 +0100 Subject: [PATCH 3/3] Add docs Signed-off-by: Jamie Hannaford Upstream-commit: 0450a2f4379231b46d90bd97f69082db7c7862b1 Component: cli --- .../cli/cli/command/container/logs_test.go | 12 +++++------ .../cli/docs/reference/commandline/logs.md | 17 ++++++++++++++++ components/cli/man/src/container/logs.md | 20 +++++++++++++++---- 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/components/cli/cli/command/container/logs_test.go b/components/cli/cli/command/container/logs_test.go index 592989da4d..da64802454 100644 --- a/components/cli/cli/command/container/logs_test.go +++ b/components/cli/cli/command/container/logs_test.go @@ -13,6 +13,12 @@ import ( "github.com/stretchr/testify/assert" ) +var logFn = func(expectedOut string) func(string, types.ContainerLogsOptions) (io.ReadCloser, error) { + return func(container string, opts types.ContainerLogsOptions) (io.ReadCloser, error) { + return ioutil.NopCloser(strings.NewReader(expectedOut)), nil + } +} + func TestRunLogs(t *testing.T) { inspectFn := func(containerID string) (types.ContainerJSON, error) { return types.ContainerJSON{ @@ -21,12 +27,6 @@ func TestRunLogs(t *testing.T) { }, nil } - logFn := func(expectedOut string) func(string, types.ContainerLogsOptions) (io.ReadCloser, error) { - return func(container string, opts types.ContainerLogsOptions) (io.ReadCloser, error) { - return ioutil.NopCloser(strings.NewReader(expectedOut)), nil - } - } - var testcases = []struct { doc string options *logsOptions diff --git a/components/cli/docs/reference/commandline/logs.md b/components/cli/docs/reference/commandline/logs.md index a71251c2d5..d004b44f90 100644 --- a/components/cli/docs/reference/commandline/logs.md +++ b/components/cli/docs/reference/commandline/logs.md @@ -25,6 +25,7 @@ Options: -f, --follow Follow log output --help Print usage --since string Show logs since timestamp (e.g. 2013-01-02T13:23:37) or relative (e.g. 42m for 42 minutes) + --until string Show logs before timestamp (e.g. 2013-01-02T13:23:37) or relative (e.g. 42m for 42 minutes) --tail string Number of lines to show from the end of the logs (default "all") -t, --timestamps Show timestamps ``` @@ -66,3 +67,19 @@ that have elapsed since January 1, 1970 (midnight UTC/GMT), not counting leap seconds (aka Unix epoch or Unix time), and the optional .nanoseconds field is a fraction of a second no more than nine digits long. You can combine the `--since` option with either or both of the `--follow` or `--tail` options. + +## Examples + +### Retrieve logs until a specific point in time + +In order to retrieve logs before a specific point in time, run: + +```bash +$ docker run --name test -d busybox sh -c "while true; do $(echo date); sleep 1; done" +$ date +Tue 14 Nov 2017 16:40:00 CET +$ docker logs -f --until=2s +Tue 14 Nov 2017 16:40:00 CET +Tue 14 Nov 2017 16:40:01 CET +Tue 14 Nov 2017 16:40:02 CET +``` \ No newline at end of file diff --git a/components/cli/man/src/container/logs.md b/components/cli/man/src/container/logs.md index c053f85758..f2b4ad6d2d 100644 --- a/components/cli/man/src/container/logs.md +++ b/components/cli/man/src/container/logs.md @@ -10,8 +10,8 @@ then continue streaming new output from the container's stdout and stderr. **Warning**: This command works only for the **json-file** or **journald** logging drivers. -The `--since` option can be Unix timestamps, date formatted timestamps, or Go -duration strings (e.g. `10m`, `1h30m`) computed relative to the client machine's +The `--since` and `--until` options can be Unix timestamps, date formatted timestamps, +or Go duration strings (e.g. `10m`, `1h30m`) computed relative to the client machine's time. Supported formats for date formatted time stamps include RFC3339Nano, RFC3339, `2006-01-02T15:04:05`, `2006-01-02T15:04:05.999999999`, `2006-01-02Z07:00`, and `2006-01-02`. The local timezone on the client will be @@ -20,9 +20,21 @@ end of the timestamp. When providing Unix timestamps enter seconds[.nanoseconds], where seconds is the number of seconds that have elapsed since January 1, 1970 (midnight UTC/GMT), not counting leap seconds (aka Unix epoch or Unix time), and the optional .nanoseconds field is a fraction of a -second no more than nine digits long. You can combine the `--since` option with -either or both of the `--follow` or `--tail` options. +second no more than nine digits long. You can combine the `--since` or `--until` +options with either or both of the `--follow` or `--tail` options. The `docker container logs --details` command will add on extra attributes, such as environment variables and labels, provided to `--log-opt` when creating the container. + +In order to retrieve logs before a specific point in time, run: + +```bash +$ docker run --name test -d busybox sh -c "while true; do $(echo date); sleep 1; done" +$ date +Tue 14 Nov 2017 16:40:00 CET +$ docker logs -f --until=2s +Tue 14 Nov 2017 16:40:00 CET +Tue 14 Nov 2017 16:40:01 CET +Tue 14 Nov 2017 16:40:02 CET +``` \ No newline at end of file