From 9892ab0af7d31c229bad9ebf842b3735e151c8e4 Mon Sep 17 00:00:00 2001 From: Ahmet Alp Balkan Date: Tue, 14 Apr 2015 04:36:12 +0000 Subject: [PATCH] Add --since argument to docker logs cmd Added --since argument to `docker logs` command. Accept unix timestamps and shows logs only created after the specified date. Default value is 0 and passing default value or not specifying the value in the request causes parameter to be ignored (behavior prior to this change). Signed-off-by: Ahmet Alp Balkan --- jsonlog/jsonlog.go | 7 +++++-- jsonlog/jsonlog_test.go | 4 ++-- timeutils/utils.go | 22 ++++++++++++++++++++++ 3 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 timeutils/utils.go diff --git a/jsonlog/jsonlog.go b/jsonlog/jsonlog.go index 261c64c..ce2da4a 100644 --- a/jsonlog/jsonlog.go +++ b/jsonlog/jsonlog.go @@ -32,16 +32,20 @@ func (jl *JSONLog) Reset() { jl.Created = time.Time{} } -func WriteLog(src io.Reader, dst io.Writer, format string) error { +func WriteLog(src io.Reader, dst io.Writer, format string, since time.Time) error { dec := json.NewDecoder(src) l := &JSONLog{} for { + l.Reset() if err := dec.Decode(l); err == io.EOF { return nil } else if err != nil { logrus.Printf("Error streaming logs: %s", err) return err } + if !since.IsZero() && l.Created.Before(since) { + continue + } line, err := l.Format(format) if err != nil { return err @@ -49,6 +53,5 @@ func WriteLog(src io.Reader, dst io.Writer, format string) error { if _, err := io.WriteString(dst, line); err != nil { return err } - l.Reset() } } diff --git a/jsonlog/jsonlog_test.go b/jsonlog/jsonlog_test.go index fa53825..d4b26fc 100644 --- a/jsonlog/jsonlog_test.go +++ b/jsonlog/jsonlog_test.go @@ -21,7 +21,7 @@ func TestWriteLog(t *testing.T) { } w := bytes.NewBuffer(nil) format := timeutils.RFC3339NanoFixed - if err := WriteLog(&buf, w, format); err != nil { + if err := WriteLog(&buf, w, format, time.Time{}); err != nil { t.Fatal(err) } res := w.String() @@ -52,7 +52,7 @@ func BenchmarkWriteLog(b *testing.B) { b.SetBytes(int64(r.Len())) b.ResetTimer() for i := 0; i < b.N; i++ { - if err := WriteLog(r, w, format); err != nil { + if err := WriteLog(r, w, format, time.Time{}); err != nil { b.Fatal(err) } b.StopTimer() diff --git a/timeutils/utils.go b/timeutils/utils.go new file mode 100644 index 0000000..c0c38fa --- /dev/null +++ b/timeutils/utils.go @@ -0,0 +1,22 @@ +package timeutils + +import ( + "strconv" + "time" +) + +// GetTimestamp tries to parse given string as RFC3339 time +// or Unix timestamp, if successful returns a Unix timestamp +// as string otherwise returns value back. +func GetTimestamp(value string) string { + format := RFC3339NanoFixed + loc := time.FixedZone(time.Now().Zone()) + if len(value) < len(format) { + format = format[:len(value)] + } + t, err := time.ParseInLocation(format, value, loc) + if err != nil { + return value + } + return strconv.FormatInt(t.Unix(), 10) +}