Signed-off-by: Lei Jitang <leijitang@huawei.com>
Lei Jitang authored on 2015/08/08 12:28:22... | ... |
@@ -97,7 +97,7 @@ func (l *JSONFileLogger) Log(msg *logger.Message) error { |
97 | 97 |
if err != nil { |
98 | 98 |
return err |
99 | 99 |
} |
100 |
- err = (&jsonlog.JSONLogBytes{Log: append(msg.Line, '\n'), Stream: msg.Source, Created: timestamp}).MarshalJSONBuf(l.buf) |
|
100 |
+ err = (&jsonlog.JSONLogs{Log: append(msg.Line, '\n'), Stream: msg.Source, Created: timestamp}).MarshalJSONBuf(l.buf) |
|
101 | 101 |
if err != nil { |
102 | 102 |
return err |
103 | 103 |
} |
... | ... |
@@ -6,12 +6,21 @@ import ( |
6 | 6 |
"time" |
7 | 7 |
) |
8 | 8 |
|
9 |
+// JSONLog represents a log message, typically a single entry from a given log stream. |
|
10 |
+// JSONLogs can be easily serialized to and from JSON and support custom formatting. |
|
9 | 11 |
type JSONLog struct { |
10 |
- Log string `json:"log,omitempty"` |
|
11 |
- Stream string `json:"stream,omitempty"` |
|
12 |
+ // Log is the log message |
|
13 |
+ Log string `json:"log,omitempty"` |
|
14 |
+ // Stream is the log source |
|
15 |
+ Stream string `json:"stream,omitempty"` |
|
16 |
+ // Created is the created timestamp of log |
|
12 | 17 |
Created time.Time `json:"time"` |
13 | 18 |
} |
14 | 19 |
|
20 |
+// Format returns the log formatted according to format |
|
21 |
+// If format is nil, returns the log message |
|
22 |
+// If format is json, returns the log marshalled in json format |
|
23 |
+// By defalut, returns the log with the log time formatted according to format. |
|
15 | 24 |
func (jl *JSONLog) Format(format string) (string, error) { |
16 | 25 |
if format == "" { |
17 | 26 |
return jl.Log, nil |
... | ... |
@@ -23,6 +32,7 @@ func (jl *JSONLog) Format(format string) (string, error) { |
23 | 23 |
return fmt.Sprintf("%s %s", jl.Created.Format(format), jl.Log), nil |
24 | 24 |
} |
25 | 25 |
|
26 |
+// Reset resets the log to nil. |
|
26 | 27 |
func (jl *JSONLog) Reset() { |
27 | 28 |
jl.Log = "" |
28 | 29 |
jl.Stream = "" |
... | ... |
@@ -61,7 +61,7 @@ |
61 | 61 |
// - } |
62 | 62 |
// + first = false |
63 | 63 |
// buf.WriteString(`"log":`) |
64 |
-// ffjson_WriteJsonString(buf, mj.Log) |
|
64 |
+// ffjsonWriteJSONString(buf, mj.Log) |
|
65 | 65 |
// } |
66 | 66 |
|
67 | 67 |
package jsonlog |
... | ... |
@@ -73,6 +73,7 @@ import ( |
73 | 73 |
"github.com/docker/docker/pkg/timeutils" |
74 | 74 |
) |
75 | 75 |
|
76 |
+// MarshalJSON marshals the JSONLog. |
|
76 | 77 |
func (mj *JSONLog) MarshalJSON() ([]byte, error) { |
77 | 78 |
var buf bytes.Buffer |
78 | 79 |
buf.Grow(1024) |
... | ... |
@@ -82,17 +83,18 @@ func (mj *JSONLog) MarshalJSON() ([]byte, error) { |
82 | 82 |
return buf.Bytes(), nil |
83 | 83 |
} |
84 | 84 |
|
85 |
+// MarshalJSONBuf marshals the JSONLog and stores the result to a bytes.Buffer. |
|
85 | 86 |
func (mj *JSONLog) MarshalJSONBuf(buf *bytes.Buffer) error { |
86 | 87 |
var ( |
87 | 88 |
err error |
88 | 89 |
timestamp string |
89 |
- first bool = true |
|
90 |
+ first = true |
|
90 | 91 |
) |
91 | 92 |
buf.WriteString(`{`) |
92 | 93 |
if len(mj.Log) != 0 { |
93 | 94 |
first = false |
94 | 95 |
buf.WriteString(`"log":`) |
95 |
- ffjson_WriteJsonString(buf, mj.Log) |
|
96 |
+ ffjsonWriteJSONString(buf, mj.Log) |
|
96 | 97 |
} |
97 | 98 |
if len(mj.Stream) != 0 { |
98 | 99 |
if first == true { |
... | ... |
@@ -101,7 +103,7 @@ func (mj *JSONLog) MarshalJSONBuf(buf *bytes.Buffer) error { |
101 | 101 |
buf.WriteString(`,`) |
102 | 102 |
} |
103 | 103 |
buf.WriteString(`"stream":`) |
104 |
- ffjson_WriteJsonString(buf, mj.Stream) |
|
104 |
+ ffjsonWriteJSONString(buf, mj.Stream) |
|
105 | 105 |
} |
106 | 106 |
if first == true { |
107 | 107 |
first = false |
... | ... |
@@ -118,7 +120,7 @@ func (mj *JSONLog) MarshalJSONBuf(buf *bytes.Buffer) error { |
118 | 118 |
return nil |
119 | 119 |
} |
120 | 120 |
|
121 |
-func ffjson_WriteJsonString(buf *bytes.Buffer, s string) { |
|
121 |
+func ffjsonWriteJSONString(buf *bytes.Buffer, s string) { |
|
122 | 122 |
const hex = "0123456789abcdef" |
123 | 123 |
|
124 | 124 |
buf.WriteByte('"') |
... | ... |
@@ -5,10 +5,10 @@ import ( |
5 | 5 |
"unicode/utf8" |
6 | 6 |
) |
7 | 7 |
|
8 |
-// JSONLogBytes is based on JSONLog. |
|
8 |
+// JSONLogs is based on JSONLog. |
|
9 | 9 |
// It allows marshalling JSONLog from Log as []byte |
10 | 10 |
// and an already marshalled Created timestamp. |
11 |
-type JSONLogBytes struct { |
|
11 |
+type JSONLogs struct { |
|
12 | 12 |
Log []byte `json:"log,omitempty"` |
13 | 13 |
Stream string `json:"stream,omitempty"` |
14 | 14 |
Created string `json:"time"` |
... | ... |
@@ -16,14 +16,14 @@ type JSONLogBytes struct { |
16 | 16 |
|
17 | 17 |
// MarshalJSONBuf is based on the same method from JSONLog |
18 | 18 |
// It has been modified to take into account the necessary changes. |
19 |
-func (mj *JSONLogBytes) MarshalJSONBuf(buf *bytes.Buffer) error { |
|
19 |
+func (mj *JSONLogs) MarshalJSONBuf(buf *bytes.Buffer) error { |
|
20 | 20 |
var first = true |
21 | 21 |
|
22 | 22 |
buf.WriteString(`{`) |
23 | 23 |
if len(mj.Log) != 0 { |
24 | 24 |
first = false |
25 | 25 |
buf.WriteString(`"log":`) |
26 |
- ffjson_WriteJsonBytesAsString(buf, mj.Log) |
|
26 |
+ ffjsonWriteJSONBytesAsString(buf, mj.Log) |
|
27 | 27 |
} |
28 | 28 |
if len(mj.Stream) != 0 { |
29 | 29 |
if first == true { |
... | ... |
@@ -32,7 +32,7 @@ func (mj *JSONLogBytes) MarshalJSONBuf(buf *bytes.Buffer) error { |
32 | 32 |
buf.WriteString(`,`) |
33 | 33 |
} |
34 | 34 |
buf.WriteString(`"stream":`) |
35 |
- ffjson_WriteJsonString(buf, mj.Stream) |
|
35 |
+ ffjsonWriteJSONString(buf, mj.Stream) |
|
36 | 36 |
} |
37 | 37 |
if first == true { |
38 | 38 |
first = false |
... | ... |
@@ -45,9 +45,9 @@ func (mj *JSONLogBytes) MarshalJSONBuf(buf *bytes.Buffer) error { |
45 | 45 |
return nil |
46 | 46 |
} |
47 | 47 |
|
48 |
-// This is based on ffjson_WriteJsonString. It has been changed |
|
48 |
+// This is based on ffjsonWriteJSONBytesAsString. It has been changed |
|
49 | 49 |
// to accept a string passed as a slice of bytes. |
50 |
-func ffjson_WriteJsonBytesAsString(buf *bytes.Buffer, s []byte) { |
|
50 |
+func ffjsonWriteJSONBytesAsString(buf *bytes.Buffer, s []byte) { |
|
51 | 51 |
const hex = "0123456789abcdef" |
52 | 52 |
|
53 | 53 |
buf.WriteByte('"') |
... | ... |
@@ -6,21 +6,21 @@ import ( |
6 | 6 |
"testing" |
7 | 7 |
) |
8 | 8 |
|
9 |
-func TestJSONLogBytesMarshalJSONBuf(t *testing.T) { |
|
10 |
- logs := map[*JSONLogBytes]string{ |
|
11 |
- &JSONLogBytes{Log: []byte(`"A log line with \\"`)}: `^{\"log\":\"\\\"A log line with \\\\\\\\\\\"\",\"time\":}$`, |
|
12 |
- &JSONLogBytes{Log: []byte("A log line")}: `^{\"log\":\"A log line\",\"time\":}$`, |
|
13 |
- &JSONLogBytes{Log: []byte("A log line with \r")}: `^{\"log\":\"A log line with \\r\",\"time\":}$`, |
|
14 |
- &JSONLogBytes{Log: []byte("A log line with & < >")}: `^{\"log\":\"A log line with \\u0026 \\u003c \\u003e\",\"time\":}$`, |
|
15 |
- &JSONLogBytes{Log: []byte("A log line with utf8 : 🚀 ψ ω β")}: `^{\"log\":\"A log line with utf8 : 🚀 ψ ω β\",\"time\":}$`, |
|
16 |
- &JSONLogBytes{Stream: "stdout"}: `^{\"stream\":\"stdout\",\"time\":}$`, |
|
17 |
- &JSONLogBytes{Stream: "stdout", Log: []byte("A log line")}: `^{\"log\":\"A log line\",\"stream\":\"stdout\",\"time\":}$`, |
|
18 |
- &JSONLogBytes{Created: "time"}: `^{\"time\":time}$`, |
|
19 |
- &JSONLogBytes{}: `^{\"time\":}$`, |
|
9 |
+func TestJSONLogsMarshalJSONBuf(t *testing.T) { |
|
10 |
+ logs := map[*JSONLogs]string{ |
|
11 |
+ &JSONLogs{Log: []byte(`"A log line with \\"`)}: `^{\"log\":\"\\\"A log line with \\\\\\\\\\\"\",\"time\":}$`, |
|
12 |
+ &JSONLogs{Log: []byte("A log line")}: `^{\"log\":\"A log line\",\"time\":}$`, |
|
13 |
+ &JSONLogs{Log: []byte("A log line with \r")}: `^{\"log\":\"A log line with \\r\",\"time\":}$`, |
|
14 |
+ &JSONLogs{Log: []byte("A log line with & < >")}: `^{\"log\":\"A log line with \\u0026 \\u003c \\u003e\",\"time\":}$`, |
|
15 |
+ &JSONLogs{Log: []byte("A log line with utf8 : 🚀 ψ ω β")}: `^{\"log\":\"A log line with utf8 : 🚀 ψ ω β\",\"time\":}$`, |
|
16 |
+ &JSONLogs{Stream: "stdout"}: `^{\"stream\":\"stdout\",\"time\":}$`, |
|
17 |
+ &JSONLogs{Stream: "stdout", Log: []byte("A log line")}: `^{\"log\":\"A log line\",\"stream\":\"stdout\",\"time\":}$`, |
|
18 |
+ &JSONLogs{Created: "time"}: `^{\"time\":time}$`, |
|
19 |
+ &JSONLogs{}: `^{\"time\":}$`, |
|
20 | 20 |
// These ones are a little weird |
21 |
- &JSONLogBytes{Log: []byte("\u2028 \u2029")}: `^{\"log\":\"\\u2028 \\u2029\",\"time\":}$`, |
|
22 |
- &JSONLogBytes{Log: []byte{0xaF}}: `^{\"log\":\"\\ufffd\",\"time\":}$`, |
|
23 |
- &JSONLogBytes{Log: []byte{0x7F}}: `^{\"log\":\"\x7f\",\"time\":}$`, |
|
21 |
+ &JSONLogs{Log: []byte("\u2028 \u2029")}: `^{\"log\":\"\\u2028 \\u2029\",\"time\":}$`, |
|
22 |
+ &JSONLogs{Log: []byte{0xaF}}: `^{\"log\":\"\\ufffd\",\"time\":}$`, |
|
23 |
+ &JSONLogs{Log: []byte{0x7F}}: `^{\"log\":\"\x7f\",\"time\":}$`, |
|
24 | 24 |
} |
25 | 25 |
for jsonLog, expression := range logs { |
26 | 26 |
var buf bytes.Buffer |
... | ... |
@@ -12,6 +12,8 @@ import ( |
12 | 12 |
"github.com/docker/docker/pkg/units" |
13 | 13 |
) |
14 | 14 |
|
15 |
+// JSONError wraps a concrete Code and Message, `Code` is |
|
16 |
+// is a integer error code, `Message` is the error message. |
|
15 | 17 |
type JSONError struct { |
16 | 18 |
Code int `json:"code,omitempty"` |
17 | 19 |
Message string `json:"message,omitempty"` |
... | ... |
@@ -21,6 +23,10 @@ func (e *JSONError) Error() string { |
21 | 21 |
return e.Message |
22 | 22 |
} |
23 | 23 |
|
24 |
+// JSONProgress describes a Progress. terminalFd is the fd of the current terminal, |
|
25 |
+// Start is the initial value for the operation. Current is the current status and |
|
26 |
+// value of the progress made towards Total. Total is the end value describing when |
|
27 |
+// we made 100% progress for an operation. |
|
24 | 28 |
type JSONProgress struct { |
25 | 29 |
terminalFd uintptr |
26 | 30 |
Current int64 `json:"current,omitempty"` |
... | ... |
@@ -76,6 +82,9 @@ func (p *JSONProgress) String() string { |
76 | 76 |
return pbBox + numbersBox + timeLeftBox |
77 | 77 |
} |
78 | 78 |
|
79 |
+// JSONMessage defines a message struct. It describes |
|
80 |
+// the created time, where it from, status, ID of the |
|
81 |
+// message. It's used for docker events. |
|
79 | 82 |
type JSONMessage struct { |
80 | 83 |
Stream string `json:"stream,omitempty"` |
81 | 84 |
Status string `json:"status,omitempty"` |
... | ... |
@@ -88,6 +97,9 @@ type JSONMessage struct { |
88 | 88 |
ErrorMessage string `json:"error,omitempty"` //deprecated |
89 | 89 |
} |
90 | 90 |
|
91 |
+// Display displays the JSONMessage to `out`. `isTerminal` describes if `out` |
|
92 |
+// is a terminal. If this is the case, it will erase the entire current line |
|
93 |
+// when dislaying the progressbar. |
|
91 | 94 |
func (jm *JSONMessage) Display(out io.Writer, isTerminal bool) error { |
92 | 95 |
if jm.Error != nil { |
93 | 96 |
if jm.Error.Code == 401 { |
... | ... |
@@ -124,6 +136,9 @@ func (jm *JSONMessage) Display(out io.Writer, isTerminal bool) error { |
124 | 124 |
return nil |
125 | 125 |
} |
126 | 126 |
|
127 |
+// DisplayJSONMessagesStream displays a json message stream from `in` to `out`, `isTerminal` |
|
128 |
+// describes if `out` is a terminal. If this is the case, it will print `\n` at the end of |
|
129 |
+// each line and move the cursor while displaying. |
|
127 | 130 |
func DisplayJSONMessagesStream(in io.Reader, out io.Writer, terminalFd uintptr, isTerminal bool) error { |
128 | 131 |
var ( |
129 | 132 |
dec = json.NewDecoder(in) |