diff --git a/jsonlog/jsonlog.go b/jsonlog/jsonlog.go index edcf764..9a71769 100644 --- a/jsonlog/jsonlog.go +++ b/jsonlog/jsonlog.go @@ -6,12 +6,21 @@ import ( "time" ) +// JSONLog represents a log message, typically a single entry from a given log stream. +// JSONLogs can be easily serialized to and from JSON and support custom formatting. type JSONLog struct { - Log string `json:"log,omitempty"` - Stream string `json:"stream,omitempty"` + // Log is the log message + Log string `json:"log,omitempty"` + // Stream is the log source + Stream string `json:"stream,omitempty"` + // Created is the created timestamp of log Created time.Time `json:"time"` } +// Format returns the log formatted according to format +// If format is nil, returns the log message +// If format is json, returns the log marshalled in json format +// By defalut, returns the log with the log time formatted according to format. func (jl *JSONLog) Format(format string) (string, error) { if format == "" { return jl.Log, nil @@ -23,6 +32,7 @@ func (jl *JSONLog) Format(format string) (string, error) { return fmt.Sprintf("%s %s", jl.Created.Format(format), jl.Log), nil } +// Reset resets the log to nil. func (jl *JSONLog) Reset() { jl.Log = "" jl.Stream = "" diff --git a/jsonlog/jsonlog_marshalling.go b/jsonlog/jsonlog_marshalling.go index 6bfec48..6dcb69d 100644 --- a/jsonlog/jsonlog_marshalling.go +++ b/jsonlog/jsonlog_marshalling.go @@ -61,7 +61,7 @@ // - } // + first = false // buf.WriteString(`"log":`) -// ffjson_WriteJsonString(buf, mj.Log) +// ffjsonWriteJSONString(buf, mj.Log) // } package jsonlog @@ -73,6 +73,7 @@ import ( "github.com/docker/docker/pkg/timeutils" ) +// MarshalJSON marshals the JSONLog. func (mj *JSONLog) MarshalJSON() ([]byte, error) { var buf bytes.Buffer buf.Grow(1024) @@ -82,17 +83,18 @@ func (mj *JSONLog) MarshalJSON() ([]byte, error) { return buf.Bytes(), nil } +// MarshalJSONBuf marshals the JSONLog and stores the result to a bytes.Buffer. func (mj *JSONLog) MarshalJSONBuf(buf *bytes.Buffer) error { var ( err error timestamp string - first bool = true + first = true ) buf.WriteString(`{`) if len(mj.Log) != 0 { first = false buf.WriteString(`"log":`) - ffjson_WriteJsonString(buf, mj.Log) + ffjsonWriteJSONString(buf, mj.Log) } if len(mj.Stream) != 0 { if first == true { @@ -101,7 +103,7 @@ func (mj *JSONLog) MarshalJSONBuf(buf *bytes.Buffer) error { buf.WriteString(`,`) } buf.WriteString(`"stream":`) - ffjson_WriteJsonString(buf, mj.Stream) + ffjsonWriteJSONString(buf, mj.Stream) } if first == true { first = false @@ -118,7 +120,7 @@ func (mj *JSONLog) MarshalJSONBuf(buf *bytes.Buffer) error { return nil } -func ffjson_WriteJsonString(buf *bytes.Buffer, s string) { +func ffjsonWriteJSONString(buf *bytes.Buffer, s string) { const hex = "0123456789abcdef" buf.WriteByte('"') diff --git a/jsonlog/jsonlogbytes.go b/jsonlog/jsonlogbytes.go index 81a966b..b2b1f98 100644 --- a/jsonlog/jsonlogbytes.go +++ b/jsonlog/jsonlogbytes.go @@ -5,10 +5,10 @@ import ( "unicode/utf8" ) -// JSONLogBytes is based on JSONLog. +// JSONLogs is based on JSONLog. // It allows marshalling JSONLog from Log as []byte // and an already marshalled Created timestamp. -type JSONLogBytes struct { +type JSONLogs struct { Log []byte `json:"log,omitempty"` Stream string `json:"stream,omitempty"` Created string `json:"time"` @@ -16,14 +16,14 @@ type JSONLogBytes struct { // MarshalJSONBuf is based on the same method from JSONLog // It has been modified to take into account the necessary changes. -func (mj *JSONLogBytes) MarshalJSONBuf(buf *bytes.Buffer) error { +func (mj *JSONLogs) MarshalJSONBuf(buf *bytes.Buffer) error { var first = true buf.WriteString(`{`) if len(mj.Log) != 0 { first = false buf.WriteString(`"log":`) - ffjson_WriteJsonBytesAsString(buf, mj.Log) + ffjsonWriteJSONBytesAsString(buf, mj.Log) } if len(mj.Stream) != 0 { if first == true { @@ -32,7 +32,7 @@ func (mj *JSONLogBytes) MarshalJSONBuf(buf *bytes.Buffer) error { buf.WriteString(`,`) } buf.WriteString(`"stream":`) - ffjson_WriteJsonString(buf, mj.Stream) + ffjsonWriteJSONString(buf, mj.Stream) } if first == true { first = false @@ -45,9 +45,9 @@ func (mj *JSONLogBytes) MarshalJSONBuf(buf *bytes.Buffer) error { return nil } -// This is based on ffjson_WriteJsonString. It has been changed +// This is based on ffjsonWriteJSONBytesAsString. It has been changed // to accept a string passed as a slice of bytes. -func ffjson_WriteJsonBytesAsString(buf *bytes.Buffer, s []byte) { +func ffjsonWriteJSONBytesAsString(buf *bytes.Buffer, s []byte) { const hex = "0123456789abcdef" buf.WriteByte('"') diff --git a/jsonlog/jsonlogbytes_test.go b/jsonlog/jsonlogbytes_test.go index 46ec52c..6c36828 100644 --- a/jsonlog/jsonlogbytes_test.go +++ b/jsonlog/jsonlogbytes_test.go @@ -6,21 +6,21 @@ import ( "testing" ) -func TestJSONLogBytesMarshalJSONBuf(t *testing.T) { - logs := map[*JSONLogBytes]string{ - &JSONLogBytes{Log: []byte(`"A log line with \\"`)}: `^{\"log\":\"\\\"A log line with \\\\\\\\\\\"\",\"time\":}$`, - &JSONLogBytes{Log: []byte("A log line")}: `^{\"log\":\"A log line\",\"time\":}$`, - &JSONLogBytes{Log: []byte("A log line with \r")}: `^{\"log\":\"A log line with \\r\",\"time\":}$`, - &JSONLogBytes{Log: []byte("A log line with & < >")}: `^{\"log\":\"A log line with \\u0026 \\u003c \\u003e\",\"time\":}$`, - &JSONLogBytes{Log: []byte("A log line with utf8 : 🚀 ψ ω β")}: `^{\"log\":\"A log line with utf8 : 🚀 ψ ω β\",\"time\":}$`, - &JSONLogBytes{Stream: "stdout"}: `^{\"stream\":\"stdout\",\"time\":}$`, - &JSONLogBytes{Stream: "stdout", Log: []byte("A log line")}: `^{\"log\":\"A log line\",\"stream\":\"stdout\",\"time\":}$`, - &JSONLogBytes{Created: "time"}: `^{\"time\":time}$`, - &JSONLogBytes{}: `^{\"time\":}$`, +func TestJSONLogsMarshalJSONBuf(t *testing.T) { + logs := map[*JSONLogs]string{ + &JSONLogs{Log: []byte(`"A log line with \\"`)}: `^{\"log\":\"\\\"A log line with \\\\\\\\\\\"\",\"time\":}$`, + &JSONLogs{Log: []byte("A log line")}: `^{\"log\":\"A log line\",\"time\":}$`, + &JSONLogs{Log: []byte("A log line with \r")}: `^{\"log\":\"A log line with \\r\",\"time\":}$`, + &JSONLogs{Log: []byte("A log line with & < >")}: `^{\"log\":\"A log line with \\u0026 \\u003c \\u003e\",\"time\":}$`, + &JSONLogs{Log: []byte("A log line with utf8 : 🚀 ψ ω β")}: `^{\"log\":\"A log line with utf8 : 🚀 ψ ω β\",\"time\":}$`, + &JSONLogs{Stream: "stdout"}: `^{\"stream\":\"stdout\",\"time\":}$`, + &JSONLogs{Stream: "stdout", Log: []byte("A log line")}: `^{\"log\":\"A log line\",\"stream\":\"stdout\",\"time\":}$`, + &JSONLogs{Created: "time"}: `^{\"time\":time}$`, + &JSONLogs{}: `^{\"time\":}$`, // These ones are a little weird - &JSONLogBytes{Log: []byte("\u2028 \u2029")}: `^{\"log\":\"\\u2028 \\u2029\",\"time\":}$`, - &JSONLogBytes{Log: []byte{0xaF}}: `^{\"log\":\"\\ufffd\",\"time\":}$`, - &JSONLogBytes{Log: []byte{0x7F}}: `^{\"log\":\"\x7f\",\"time\":}$`, + &JSONLogs{Log: []byte("\u2028 \u2029")}: `^{\"log\":\"\\u2028 \\u2029\",\"time\":}$`, + &JSONLogs{Log: []byte{0xaF}}: `^{\"log\":\"\\ufffd\",\"time\":}$`, + &JSONLogs{Log: []byte{0x7F}}: `^{\"log\":\"\x7f\",\"time\":}$`, } for jsonLog, expression := range logs { var buf bytes.Buffer diff --git a/jsonmessage/jsonmessage.go b/jsonmessage/jsonmessage.go index 0c93ee6..f3bcc8e 100644 --- a/jsonmessage/jsonmessage.go +++ b/jsonmessage/jsonmessage.go @@ -12,6 +12,8 @@ import ( "github.com/docker/docker/pkg/units" ) +// JSONError wraps a concrete Code and Message, `Code` is +// is a integer error code, `Message` is the error message. type JSONError struct { Code int `json:"code,omitempty"` Message string `json:"message,omitempty"` @@ -21,6 +23,10 @@ func (e *JSONError) Error() string { return e.Message } +// JSONProgress describes a Progress. terminalFd is the fd of the current terminal, +// Start is the initial value for the operation. Current is the current status and +// value of the progress made towards Total. Total is the end value describing when +// we made 100% progress for an operation. type JSONProgress struct { terminalFd uintptr Current int64 `json:"current,omitempty"` @@ -76,6 +82,9 @@ func (p *JSONProgress) String() string { return pbBox + numbersBox + timeLeftBox } +// JSONMessage defines a message struct. It describes +// the created time, where it from, status, ID of the +// message. It's used for docker events. type JSONMessage struct { Stream string `json:"stream,omitempty"` Status string `json:"status,omitempty"` @@ -88,6 +97,9 @@ type JSONMessage struct { ErrorMessage string `json:"error,omitempty"` //deprecated } +// Display displays the JSONMessage to `out`. `isTerminal` describes if `out` +// is a terminal. If this is the case, it will erase the entire current line +// when dislaying the progressbar. func (jm *JSONMessage) Display(out io.Writer, isTerminal bool) error { if jm.Error != nil { if jm.Error.Code == 401 { @@ -124,6 +136,9 @@ func (jm *JSONMessage) Display(out io.Writer, isTerminal bool) error { return nil } +// DisplayJSONMessagesStream displays a json message stream from `in` to `out`, `isTerminal` +// describes if `out` is a terminal. If this is the case, it will print `\n` at the end of +// each line and move the cursor while displaying. func DisplayJSONMessagesStream(in io.Reader, out io.Writer, terminalFd uintptr, isTerminal bool) error { var ( dec = json.NewDecoder(in)