Browse code

Move jsonlog to a subpackage of jsonfilelog

Signed-off-by: Daniel Nephin <dnephin@docker.com>

Daniel Nephin authored on 2017/09/26 04:57:45
Showing 14 changed files
... ...
@@ -12,8 +12,8 @@ import (
12 12
 	"sync"
13 13
 
14 14
 	"github.com/docker/docker/daemon/logger"
15
+	"github.com/docker/docker/daemon/logger/jsonfilelog/jsonlog"
15 16
 	"github.com/docker/docker/daemon/logger/loggerutils"
16
-	"github.com/docker/docker/pkg/jsonlog"
17 17
 	units "github.com/docker/go-units"
18 18
 	"github.com/pkg/errors"
19 19
 	"github.com/sirupsen/logrus"
... ...
@@ -12,7 +12,7 @@ import (
12 12
 	"time"
13 13
 
14 14
 	"github.com/docker/docker/daemon/logger"
15
-	"github.com/docker/docker/pkg/jsonlog"
15
+	"github.com/docker/docker/daemon/logger/jsonfilelog/jsonlog"
16 16
 	"github.com/gotestyourself/gotestyourself/fs"
17 17
 	"github.com/stretchr/testify/require"
18 18
 )
19 19
new file mode 100644
... ...
@@ -0,0 +1,25 @@
0
+package jsonlog
1
+
2
+import (
3
+	"time"
4
+)
5
+
6
+// JSONLog is a log message, typically a single entry from a given log stream.
7
+type JSONLog struct {
8
+	// Log is the log message
9
+	Log string `json:"log,omitempty"`
10
+	// Stream is the log source
11
+	Stream string `json:"stream,omitempty"`
12
+	// Created is the created timestamp of log
13
+	Created time.Time `json:"time"`
14
+	// Attrs is the list of extra attributes provided by the user
15
+	Attrs map[string]string `json:"attrs,omitempty"`
16
+}
17
+
18
+// Reset all fields to their zero value.
19
+func (jl *JSONLog) Reset() {
20
+	jl.Log = ""
21
+	jl.Stream = ""
22
+	jl.Created = time.Time{}
23
+	jl.Attrs = make(map[string]string)
24
+}
0 25
new file mode 100644
... ...
@@ -0,0 +1,125 @@
0
+package jsonlog
1
+
2
+import (
3
+	"bytes"
4
+	"encoding/json"
5
+	"time"
6
+	"unicode/utf8"
7
+)
8
+
9
+// JSONLogs marshals encoded JSONLog objects
10
+type JSONLogs struct {
11
+	Log     []byte    `json:"log,omitempty"`
12
+	Stream  string    `json:"stream,omitempty"`
13
+	Created time.Time `json:"time"`
14
+
15
+	// json-encoded bytes
16
+	RawAttrs json.RawMessage `json:"attrs,omitempty"`
17
+}
18
+
19
+// MarshalJSONBuf is an optimized JSON marshaller that avoids reflection
20
+// and unnecessary allocation.
21
+func (mj *JSONLogs) MarshalJSONBuf(buf *bytes.Buffer) error {
22
+	var first = true
23
+
24
+	buf.WriteString(`{`)
25
+	if len(mj.Log) != 0 {
26
+		first = false
27
+		buf.WriteString(`"log":`)
28
+		ffjsonWriteJSONBytesAsString(buf, mj.Log)
29
+	}
30
+	if len(mj.Stream) != 0 {
31
+		if first {
32
+			first = false
33
+		} else {
34
+			buf.WriteString(`,`)
35
+		}
36
+		buf.WriteString(`"stream":`)
37
+		ffjsonWriteJSONBytesAsString(buf, []byte(mj.Stream))
38
+	}
39
+	if len(mj.RawAttrs) > 0 {
40
+		if first {
41
+			first = false
42
+		} else {
43
+			buf.WriteString(`,`)
44
+		}
45
+		buf.WriteString(`"attrs":`)
46
+		buf.Write(mj.RawAttrs)
47
+	}
48
+	if !first {
49
+		buf.WriteString(`,`)
50
+	}
51
+
52
+	created, err := fastTimeMarshalJSON(mj.Created)
53
+	if err != nil {
54
+		return err
55
+	}
56
+
57
+	buf.WriteString(`"time":`)
58
+	buf.WriteString(created)
59
+	buf.WriteString(`}`)
60
+	return nil
61
+}
62
+
63
+func ffjsonWriteJSONBytesAsString(buf *bytes.Buffer, s []byte) {
64
+	const hex = "0123456789abcdef"
65
+
66
+	buf.WriteByte('"')
67
+	start := 0
68
+	for i := 0; i < len(s); {
69
+		if b := s[i]; b < utf8.RuneSelf {
70
+			if 0x20 <= b && b != '\\' && b != '"' && b != '<' && b != '>' && b != '&' {
71
+				i++
72
+				continue
73
+			}
74
+			if start < i {
75
+				buf.Write(s[start:i])
76
+			}
77
+			switch b {
78
+			case '\\', '"':
79
+				buf.WriteByte('\\')
80
+				buf.WriteByte(b)
81
+			case '\n':
82
+				buf.WriteByte('\\')
83
+				buf.WriteByte('n')
84
+			case '\r':
85
+				buf.WriteByte('\\')
86
+				buf.WriteByte('r')
87
+			default:
88
+
89
+				buf.WriteString(`\u00`)
90
+				buf.WriteByte(hex[b>>4])
91
+				buf.WriteByte(hex[b&0xF])
92
+			}
93
+			i++
94
+			start = i
95
+			continue
96
+		}
97
+		c, size := utf8.DecodeRune(s[i:])
98
+		if c == utf8.RuneError && size == 1 {
99
+			if start < i {
100
+				buf.Write(s[start:i])
101
+			}
102
+			buf.WriteString(`\ufffd`)
103
+			i += size
104
+			start = i
105
+			continue
106
+		}
107
+
108
+		if c == '\u2028' || c == '\u2029' {
109
+			if start < i {
110
+				buf.Write(s[start:i])
111
+			}
112
+			buf.WriteString(`\u202`)
113
+			buf.WriteByte(hex[c&0xF])
114
+			i += size
115
+			start = i
116
+			continue
117
+		}
118
+		i += size
119
+	}
120
+	if start < len(s) {
121
+		buf.Write(s[start:])
122
+	}
123
+	buf.WriteByte('"')
124
+}
0 125
new file mode 100644
... ...
@@ -0,0 +1,40 @@
0
+package jsonlog
1
+
2
+import (
3
+	"bytes"
4
+	"encoding/json"
5
+	"regexp"
6
+	"testing"
7
+	"time"
8
+
9
+	"github.com/stretchr/testify/assert"
10
+	"github.com/stretchr/testify/require"
11
+)
12
+
13
+func TestJSONLogsMarshalJSONBuf(t *testing.T) {
14
+	logs := map[*JSONLogs]string{
15
+		{Log: []byte(`"A log line with \\"`)}:                  `^{\"log\":\"\\\"A log line with \\\\\\\\\\\"\",\"time\":`,
16
+		{Log: []byte("A log line")}:                            `^{\"log\":\"A log line\",\"time\":`,
17
+		{Log: []byte("A log line with \r")}:                    `^{\"log\":\"A log line with \\r\",\"time\":`,
18
+		{Log: []byte("A log line with & < >")}:                 `^{\"log\":\"A log line with \\u0026 \\u003c \\u003e\",\"time\":`,
19
+		{Log: []byte("A log line with utf8 : 🚀 ψ ω β")}:        `^{\"log\":\"A log line with utf8 : 🚀 ψ ω β\",\"time\":`,
20
+		{Stream: "stdout"}:                                     `^{\"stream\":\"stdout\",\"time\":`,
21
+		{Stream: "stdout", Log: []byte("A log line")}:          `^{\"log\":\"A log line\",\"stream\":\"stdout\",\"time\":`,
22
+		{Created: time.Date(2017, 9, 1, 1, 1, 1, 1, time.UTC)}: `^{\"time\":"2017-09-01T01:01:01.000000001Z"}$`,
23
+
24
+		{}: `^{\"time\":"0001-01-01T00:00:00Z"}$`,
25
+		// These ones are a little weird
26
+		{Log: []byte("\u2028 \u2029")}: `^{\"log\":\"\\u2028 \\u2029\",\"time\":`,
27
+		{Log: []byte{0xaF}}:            `^{\"log\":\"\\ufffd\",\"time\":`,
28
+		{Log: []byte{0x7F}}:            `^{\"log\":\"\x7f\",\"time\":`,
29
+		// with raw attributes
30
+		{Log: []byte("A log line"), RawAttrs: []byte(`{"hello":"world","value":1234}`)}: `^{\"log\":\"A log line\",\"attrs\":{\"hello\":\"world\",\"value\":1234},\"time\":`,
31
+	}
32
+	for jsonLog, expression := range logs {
33
+		var buf bytes.Buffer
34
+		err := jsonLog.MarshalJSONBuf(&buf)
35
+		require.NoError(t, err)
36
+		assert.Regexp(t, regexp.MustCompile(expression), buf.String())
37
+		assert.NoError(t, json.Unmarshal(buf.Bytes(), &map[string]interface{}{}))
38
+	}
39
+}
0 40
new file mode 100644
... ...
@@ -0,0 +1,20 @@
0
+package jsonlog
1
+
2
+import (
3
+	"time"
4
+
5
+	"github.com/pkg/errors"
6
+)
7
+
8
+const jsonFormat = `"` + time.RFC3339Nano + `"`
9
+
10
+// fastTimeMarshalJSON avoids one of the extra allocations that
11
+// time.MarshalJSON is making.
12
+func fastTimeMarshalJSON(t time.Time) (string, error) {
13
+	if y := t.Year(); y < 0 || y >= 10000 {
14
+		// RFC 3339 is clear that years are 4 digits exactly.
15
+		// See golang.org/issue/4556#c15 for more discussion.
16
+		return "", errors.New("time.MarshalJSON: year outside of range [0,9999]")
17
+	}
18
+	return t.Format(jsonFormat), nil
19
+}
0 20
new file mode 100644
... ...
@@ -0,0 +1,35 @@
0
+package jsonlog
1
+
2
+import (
3
+	"testing"
4
+	"time"
5
+
6
+	"github.com/docker/docker/internal/testutil"
7
+	"github.com/stretchr/testify/assert"
8
+	"github.com/stretchr/testify/require"
9
+)
10
+
11
+func TestFastTimeMarshalJSONWithInvalidYear(t *testing.T) {
12
+	aTime := time.Date(-1, 1, 1, 0, 0, 0, 0, time.Local)
13
+	_, err := fastTimeMarshalJSON(aTime)
14
+	testutil.ErrorContains(t, err, "year outside of range")
15
+
16
+	anotherTime := time.Date(10000, 1, 1, 0, 0, 0, 0, time.Local)
17
+	_, err = fastTimeMarshalJSON(anotherTime)
18
+	testutil.ErrorContains(t, err, "year outside of range")
19
+}
20
+
21
+func TestFastTimeMarshalJSON(t *testing.T) {
22
+	aTime := time.Date(2015, 5, 29, 11, 1, 2, 3, time.UTC)
23
+	json, err := fastTimeMarshalJSON(aTime)
24
+	require.NoError(t, err)
25
+	assert.Equal(t, "\"2015-05-29T11:01:02.000000003Z\"", json)
26
+
27
+	location, err := time.LoadLocation("Europe/Paris")
28
+	require.NoError(t, err)
29
+
30
+	aTime = time.Date(2015, 5, 29, 11, 1, 2, 3, location)
31
+	json, err = fastTimeMarshalJSON(aTime)
32
+	require.NoError(t, err)
33
+	assert.Equal(t, "\"2015-05-29T11:01:02.000000003+02:00\"", json)
34
+}
... ...
@@ -13,9 +13,9 @@ import (
13 13
 
14 14
 	"github.com/docker/docker/api/types/backend"
15 15
 	"github.com/docker/docker/daemon/logger"
16
+	"github.com/docker/docker/daemon/logger/jsonfilelog/jsonlog"
16 17
 	"github.com/docker/docker/daemon/logger/jsonfilelog/multireader"
17 18
 	"github.com/docker/docker/pkg/filenotify"
18
-	"github.com/docker/docker/pkg/jsonlog"
19 19
 	"github.com/docker/docker/pkg/tailfile"
20 20
 	"github.com/pkg/errors"
21 21
 	"github.com/sirupsen/logrus"
... ...
@@ -1,9 +1,8 @@
1 1
 package jsonfilelog
2 2
 
3 3
 import (
4
-	"testing"
5
-
6 4
 	"bytes"
5
+	"testing"
7 6
 	"time"
8 7
 
9 8
 	"github.com/docker/docker/daemon/logger"
10 9
deleted file mode 100644
... ...
@@ -1,25 +0,0 @@
1
-package jsonlog
2
-
3
-import (
4
-	"time"
5
-)
6
-
7
-// JSONLog is a log message, typically a single entry from a given log stream.
8
-type JSONLog struct {
9
-	// Log is the log message
10
-	Log string `json:"log,omitempty"`
11
-	// Stream is the log source
12
-	Stream string `json:"stream,omitempty"`
13
-	// Created is the created timestamp of log
14
-	Created time.Time `json:"time"`
15
-	// Attrs is the list of extra attributes provided by the user
16
-	Attrs map[string]string `json:"attrs,omitempty"`
17
-}
18
-
19
-// Reset all fields to their zero value.
20
-func (jl *JSONLog) Reset() {
21
-	jl.Log = ""
22
-	jl.Stream = ""
23
-	jl.Created = time.Time{}
24
-	jl.Attrs = make(map[string]string)
25
-}
26 1
deleted file mode 100644
... ...
@@ -1,125 +0,0 @@
1
-package jsonlog
2
-
3
-import (
4
-	"bytes"
5
-	"encoding/json"
6
-	"time"
7
-	"unicode/utf8"
8
-)
9
-
10
-// JSONLogs marshals encoded JSONLog objects
11
-type JSONLogs struct {
12
-	Log     []byte    `json:"log,omitempty"`
13
-	Stream  string    `json:"stream,omitempty"`
14
-	Created time.Time `json:"time"`
15
-
16
-	// json-encoded bytes
17
-	RawAttrs json.RawMessage `json:"attrs,omitempty"`
18
-}
19
-
20
-// MarshalJSONBuf is an optimized JSON marshaller that avoids reflection
21
-// and unnecessary allocation.
22
-func (mj *JSONLogs) MarshalJSONBuf(buf *bytes.Buffer) error {
23
-	var first = true
24
-
25
-	buf.WriteString(`{`)
26
-	if len(mj.Log) != 0 {
27
-		first = false
28
-		buf.WriteString(`"log":`)
29
-		ffjsonWriteJSONBytesAsString(buf, mj.Log)
30
-	}
31
-	if len(mj.Stream) != 0 {
32
-		if first {
33
-			first = false
34
-		} else {
35
-			buf.WriteString(`,`)
36
-		}
37
-		buf.WriteString(`"stream":`)
38
-		ffjsonWriteJSONBytesAsString(buf, []byte(mj.Stream))
39
-	}
40
-	if len(mj.RawAttrs) > 0 {
41
-		if first {
42
-			first = false
43
-		} else {
44
-			buf.WriteString(`,`)
45
-		}
46
-		buf.WriteString(`"attrs":`)
47
-		buf.Write(mj.RawAttrs)
48
-	}
49
-	if !first {
50
-		buf.WriteString(`,`)
51
-	}
52
-
53
-	created, err := fastTimeMarshalJSON(mj.Created)
54
-	if err != nil {
55
-		return err
56
-	}
57
-
58
-	buf.WriteString(`"time":`)
59
-	buf.WriteString(created)
60
-	buf.WriteString(`}`)
61
-	return nil
62
-}
63
-
64
-func ffjsonWriteJSONBytesAsString(buf *bytes.Buffer, s []byte) {
65
-	const hex = "0123456789abcdef"
66
-
67
-	buf.WriteByte('"')
68
-	start := 0
69
-	for i := 0; i < len(s); {
70
-		if b := s[i]; b < utf8.RuneSelf {
71
-			if 0x20 <= b && b != '\\' && b != '"' && b != '<' && b != '>' && b != '&' {
72
-				i++
73
-				continue
74
-			}
75
-			if start < i {
76
-				buf.Write(s[start:i])
77
-			}
78
-			switch b {
79
-			case '\\', '"':
80
-				buf.WriteByte('\\')
81
-				buf.WriteByte(b)
82
-			case '\n':
83
-				buf.WriteByte('\\')
84
-				buf.WriteByte('n')
85
-			case '\r':
86
-				buf.WriteByte('\\')
87
-				buf.WriteByte('r')
88
-			default:
89
-
90
-				buf.WriteString(`\u00`)
91
-				buf.WriteByte(hex[b>>4])
92
-				buf.WriteByte(hex[b&0xF])
93
-			}
94
-			i++
95
-			start = i
96
-			continue
97
-		}
98
-		c, size := utf8.DecodeRune(s[i:])
99
-		if c == utf8.RuneError && size == 1 {
100
-			if start < i {
101
-				buf.Write(s[start:i])
102
-			}
103
-			buf.WriteString(`\ufffd`)
104
-			i += size
105
-			start = i
106
-			continue
107
-		}
108
-
109
-		if c == '\u2028' || c == '\u2029' {
110
-			if start < i {
111
-				buf.Write(s[start:i])
112
-			}
113
-			buf.WriteString(`\u202`)
114
-			buf.WriteByte(hex[c&0xF])
115
-			i += size
116
-			start = i
117
-			continue
118
-		}
119
-		i += size
120
-	}
121
-	if start < len(s) {
122
-		buf.Write(s[start:])
123
-	}
124
-	buf.WriteByte('"')
125
-}
126 1
deleted file mode 100644
... ...
@@ -1,40 +0,0 @@
1
-package jsonlog
2
-
3
-import (
4
-	"bytes"
5
-	"encoding/json"
6
-	"regexp"
7
-	"testing"
8
-	"time"
9
-
10
-	"github.com/stretchr/testify/assert"
11
-	"github.com/stretchr/testify/require"
12
-)
13
-
14
-func TestJSONLogsMarshalJSONBuf(t *testing.T) {
15
-	logs := map[*JSONLogs]string{
16
-		{Log: []byte(`"A log line with \\"`)}:                  `^{\"log\":\"\\\"A log line with \\\\\\\\\\\"\",\"time\":`,
17
-		{Log: []byte("A log line")}:                            `^{\"log\":\"A log line\",\"time\":`,
18
-		{Log: []byte("A log line with \r")}:                    `^{\"log\":\"A log line with \\r\",\"time\":`,
19
-		{Log: []byte("A log line with & < >")}:                 `^{\"log\":\"A log line with \\u0026 \\u003c \\u003e\",\"time\":`,
20
-		{Log: []byte("A log line with utf8 : 🚀 ψ ω β")}:        `^{\"log\":\"A log line with utf8 : 🚀 ψ ω β\",\"time\":`,
21
-		{Stream: "stdout"}:                                     `^{\"stream\":\"stdout\",\"time\":`,
22
-		{Stream: "stdout", Log: []byte("A log line")}:          `^{\"log\":\"A log line\",\"stream\":\"stdout\",\"time\":`,
23
-		{Created: time.Date(2017, 9, 1, 1, 1, 1, 1, time.UTC)}: `^{\"time\":"2017-09-01T01:01:01.000000001Z"}$`,
24
-
25
-		{}: `^{\"time\":"0001-01-01T00:00:00Z"}$`,
26
-		// These ones are a little weird
27
-		{Log: []byte("\u2028 \u2029")}: `^{\"log\":\"\\u2028 \\u2029\",\"time\":`,
28
-		{Log: []byte{0xaF}}:            `^{\"log\":\"\\ufffd\",\"time\":`,
29
-		{Log: []byte{0x7F}}:            `^{\"log\":\"\x7f\",\"time\":`,
30
-		// with raw attributes
31
-		{Log: []byte("A log line"), RawAttrs: []byte(`{"hello":"world","value":1234}`)}: `^{\"log\":\"A log line\",\"attrs\":{\"hello\":\"world\",\"value\":1234},\"time\":`,
32
-	}
33
-	for jsonLog, expression := range logs {
34
-		var buf bytes.Buffer
35
-		err := jsonLog.MarshalJSONBuf(&buf)
36
-		require.NoError(t, err)
37
-		assert.Regexp(t, regexp.MustCompile(expression), buf.String())
38
-		assert.NoError(t, json.Unmarshal(buf.Bytes(), &map[string]interface{}{}))
39
-	}
40
-}
41 1
deleted file mode 100644
... ...
@@ -1,20 +0,0 @@
1
-package jsonlog
2
-
3
-import (
4
-	"time"
5
-
6
-	"github.com/pkg/errors"
7
-)
8
-
9
-const jsonFormat = `"` + time.RFC3339Nano + `"`
10
-
11
-// fastTimeMarshalJSON avoids one of the extra allocations that
12
-// time.MarshalJSON is making.
13
-func fastTimeMarshalJSON(t time.Time) (string, error) {
14
-	if y := t.Year(); y < 0 || y >= 10000 {
15
-		// RFC 3339 is clear that years are 4 digits exactly.
16
-		// See golang.org/issue/4556#c15 for more discussion.
17
-		return "", errors.New("time.MarshalJSON: year outside of range [0,9999]")
18
-	}
19
-	return t.Format(jsonFormat), nil
20
-}
21 1
deleted file mode 100644
... ...
@@ -1,35 +0,0 @@
1
-package jsonlog
2
-
3
-import (
4
-	"testing"
5
-	"time"
6
-
7
-	"github.com/docker/docker/internal/testutil"
8
-	"github.com/stretchr/testify/assert"
9
-	"github.com/stretchr/testify/require"
10
-)
11
-
12
-func TestFastTimeMarshalJSONWithInvalidYear(t *testing.T) {
13
-	aTime := time.Date(-1, 1, 1, 0, 0, 0, 0, time.Local)
14
-	_, err := fastTimeMarshalJSON(aTime)
15
-	testutil.ErrorContains(t, err, "year outside of range")
16
-
17
-	anotherTime := time.Date(10000, 1, 1, 0, 0, 0, 0, time.Local)
18
-	_, err = fastTimeMarshalJSON(anotherTime)
19
-	testutil.ErrorContains(t, err, "year outside of range")
20
-}
21
-
22
-func TestFastTimeMarshalJSON(t *testing.T) {
23
-	aTime := time.Date(2015, 5, 29, 11, 1, 2, 3, time.UTC)
24
-	json, err := fastTimeMarshalJSON(aTime)
25
-	require.NoError(t, err)
26
-	assert.Equal(t, "\"2015-05-29T11:01:02.000000003Z\"", json)
27
-
28
-	location, err := time.LoadLocation("Europe/Paris")
29
-	require.NoError(t, err)
30
-
31
-	aTime = time.Date(2015, 5, 29, 11, 1, 2, 3, location)
32
-	json, err = fastTimeMarshalJSON(aTime)
33
-	require.NoError(t, err)
34
-	assert.Equal(t, "\"2015-05-29T11:01:02.000000003+02:00\"", json)
35
-}