18790: Sort lines by timestamp before displaying a chunk.
authorTom Clegg <tom@curii.com>
Thu, 6 Apr 2023 02:55:21 +0000 (22:55 -0400)
committerTom Clegg <tom@curii.com>
Thu, 6 Apr 2023 02:55:21 +0000 (22:55 -0400)
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom@curii.com>

cmd/arvados-client/container_gateway.go
cmd/arvados-client/container_gateway_test.go

index 36c376e5c097371cd3a1a0cc07ecc770209047e4..b5f45199d6cb2e6eb44d6beb5dd1c27d4e9e71a0 100644 (file)
@@ -16,6 +16,7 @@ import (
        "os"
        "os/exec"
        "path/filepath"
+       "sort"
        "strings"
        "syscall"
        "time"
@@ -270,16 +271,14 @@ func (lc *logsCommand) copyRange(ctx context.Context, uuid, fnm, byterange strin
 // exit.
 func (lc *logsCommand) display(out, stderr io.Writer, watching []string, received map[string]*bytes.Buffer) bool {
        checkState := false
+       var sorted []string
        for _, fnm := range watching {
                buf := received[fnm]
                if buf == nil || buf.Len() == 0 {
                        continue
                }
                for _, line := range bytes.Split(bytes.TrimSuffix(buf.Bytes(), []byte{'\n'}), []byte{'\n'}) {
-                       _, err := fmt.Fprintf(out, "%-14s %s\n", fnm, line)
-                       if err != nil {
-                               fmt.Fprintln(stderr, err)
-                       }
+                       sorted = append(sorted, fmt.Sprintf("%-14s %s\n", fnm, line))
                        if fnm == "crunch-run.txt" {
                                checkState = checkState ||
                                        bytes.HasSuffix(line, []byte("Complete")) ||
@@ -288,6 +287,15 @@ func (lc *logsCommand) display(out, stderr io.Writer, watching []string, receive
                        }
                }
        }
+       sort.Slice(sorted, func(i, j int) bool {
+               return sorted[i][15:] < sorted[j][15:]
+       })
+       for _, s := range sorted {
+               _, err := fmt.Fprint(out, s)
+               if err != nil {
+                       fmt.Fprintln(stderr, err)
+               }
+       }
        return checkState
 }
 
index a49a58bf4d2e7b4b22b7099c3533149a6d47b42e..7c2c7d121a910bb861d5c11cd4ef675e5934e3da 100644 (file)
@@ -261,23 +261,24 @@ func (s *ClientSuite) TestContainerLog(c *check.C) {
        }})
        c.Assert(err, check.IsNil)
 
+       const rfc3339NanoFixed = "2006-01-02T15:04:05.000000000Z07:00"
        fCrunchrun, err := cfs.OpenFile("crunch-run.txt", os.O_CREATE|os.O_WRONLY, 0777)
        c.Assert(err, check.IsNil)
-       _, err = fmt.Fprintln(fCrunchrun, "line 1 of crunch-run.txt")
+       _, err = fmt.Fprintf(fCrunchrun, "%s line 1 of crunch-run.txt\n", time.Now().UTC().Format(rfc3339NanoFixed))
        c.Assert(err, check.IsNil)
        fStderr, err := cfs.OpenFile("stderr.txt", os.O_CREATE|os.O_WRONLY, 0777)
        c.Assert(err, check.IsNil)
-       _, err = fmt.Fprintln(fStderr, "line 1 of stderr")
+       _, err = fmt.Fprintf(fStderr, "%s line 1 of stderr\n", time.Now().UTC().Format(rfc3339NanoFixed))
        c.Assert(err, check.IsNil)
        time.Sleep(time.Second * 2)
-       _, err = fmt.Fprintln(fCrunchrun, "line 2 of crunch-run.txt")
+       _, err = fmt.Fprintf(fCrunchrun, "%s line 2 of crunch-run.txt", time.Now().UTC().Format(rfc3339NanoFixed))
        c.Assert(err, check.IsNil)
-       _, err = fmt.Fprintln(fStderr, "--end--")
+       _, err = fmt.Fprintf(fStderr, "%s --end--", time.Now().UTC().Format(rfc3339NanoFixed))
        c.Assert(err, check.IsNil)
 
        for deadline := time.Now().Add(20 * time.Second); time.Now().Before(deadline) && !strings.Contains(stdout.String(), "--end--"); time.Sleep(time.Second / 10) {
        }
-       c.Check(stdout.String(), check.Matches, `(?ms).*stderr\.txt +--end--\n.*`)
+       c.Check(stdout.String(), check.Matches, `(?ms).*stderr\.txt +20\S+Z --end--\n.*`)
 
        mtxt, err := cfs.MarshalManifest(".")
        c.Assert(err, check.IsNil)