1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Added tag log option to json-logger

Fixes #19803
Updated the json-logger to utilize the common log option
'tag' that can define container/image information to include
as part of logging.

When the 'tag' log option is not included, there is no change
to the log content via the json-logger. When the 'tag' log option
is included, the tag will be parsed as a template and the result
will be stored within each log entry as the attribute 'tag'.

Update: Removing test added to integration_cli as those have been deprecated.
Update: Using proper test calls (require and assert) in jsonfilelog_test.go based on review.
Update: Added new unit test configs for logs with tag. Updated unit test error checking.
Update: Cleanup check in jsonlogbytes_test.go to match pending changes in PR #34946.
Update: Merging to correct conflicts from PR #34946.

Signed-off-by: bonczj <josh.bonczkowski@gmail.com>
This commit is contained in:
bonczj 2017-09-26 10:22:10 -04:00 committed by Yong Tang
parent bb6ce89737
commit 5f50f4f511
6 changed files with 72 additions and 4 deletions

View file

@ -27,6 +27,7 @@ type JSONFileLogger struct {
closed bool
writer *loggerutils.LogFile
readers map[*logger.LogWatcher]struct{} // stores the active log followers
tag string // tag values requested by the user to log
}
func init() {
@ -61,6 +62,12 @@ func New(info logger.Info) (logger.Logger, error) {
}
}
// no default template. only use a tag if the user asked for it
tag, err := loggerutils.ParseLogTag(info, "")
if err != nil {
return nil, err
}
var extra []byte
attrs, err := info.ExtraAttributes(nil)
if err != nil {
@ -76,7 +83,7 @@ func New(info logger.Info) (logger.Logger, error) {
buf := bytes.NewBuffer(nil)
marshalFunc := func(msg *logger.Message) ([]byte, error) {
if err := marshalMessage(msg, extra, buf); err != nil {
if err := marshalMessage(msg, extra, buf, tag); err != nil {
return nil, err
}
b := buf.Bytes()
@ -92,6 +99,7 @@ func New(info logger.Info) (logger.Logger, error) {
return &JSONFileLogger{
writer: writer,
readers: make(map[*logger.LogWatcher]struct{}),
tag: tag,
}, nil
}
@ -103,7 +111,7 @@ func (l *JSONFileLogger) Log(msg *logger.Message) error {
return err
}
func marshalMessage(msg *logger.Message, extra json.RawMessage, buf *bytes.Buffer) error {
func marshalMessage(msg *logger.Message, extra json.RawMessage, buf *bytes.Buffer, tag string) error {
logLine := msg.Line
if !msg.Partial {
logLine = append(msg.Line, '\n')
@ -113,6 +121,7 @@ func marshalMessage(msg *logger.Message, extra json.RawMessage, buf *bytes.Buffe
Stream: msg.Source,
Created: msg.Timestamp,
RawAttrs: extra,
Tag: tag,
}).MarshalJSONBuf(buf)
if err != nil {
return errors.Wrap(err, "error writing log message to buffer")
@ -130,6 +139,7 @@ func ValidateLogOpt(cfg map[string]string) error {
case "labels":
case "env":
case "env-regex":
case "tag":
default:
return fmt.Errorf("unknown log opt '%s' for json-file log driver", key)
}

View file

@ -57,6 +57,49 @@ func TestJSONFileLogger(t *testing.T) {
}
}
func TestJSONFileLoggerWithTags(t *testing.T) {
cid := "a7317399f3f857173c6179d44823594f8294678dea9999662e5c625b5a1c7657"
cname := "test-container"
tmp, err := ioutil.TempDir("", "docker-logger-")
require.NoError(t, err)
defer os.RemoveAll(tmp)
filename := filepath.Join(tmp, "container.log")
l, err := New(logger.Info{
Config: map[string]string{
"tag": "{{.ID}}/{{.Name}}", // first 12 characters of ContainerID and full ContainerName
},
ContainerID: cid,
ContainerName: cname,
LogPath: filename,
})
require.NoError(t, err)
defer l.Close()
err = l.Log(&logger.Message{Line: []byte("line1"), Source: "src1"})
require.NoError(t, err)
err = l.Log(&logger.Message{Line: []byte("line2"), Source: "src2"})
require.NoError(t, err)
err = l.Log(&logger.Message{Line: []byte("line3"), Source: "src3"})
require.NoError(t, err)
res, err := ioutil.ReadFile(filename)
require.NoError(t, err)
expected := `{"log":"line1\n","stream":"src1","tag":"a7317399f3f8/test-container","time":"0001-01-01T00:00:00Z"}
{"log":"line2\n","stream":"src2","tag":"a7317399f3f8/test-container","time":"0001-01-01T00:00:00Z"}
{"log":"line3\n","stream":"src3","tag":"a7317399f3f8/test-container","time":"0001-01-01T00:00:00Z"}
`
if string(res) != expected {
t.Fatalf("Wrong log content: %q, expected %q", res, expected)
}
}
func BenchmarkJSONFileLoggerLog(b *testing.B) {
tmp := fs.NewDir(b, "bench-jsonfilelog")
defer tmp.Remove()
@ -82,7 +125,7 @@ func BenchmarkJSONFileLoggerLog(b *testing.B) {
}
buf := bytes.NewBuffer(nil)
require.NoError(b, marshalMessage(msg, nil, buf))
require.NoError(b, marshalMessage(msg, nil, buf, ""))
b.SetBytes(int64(buf.Len()))
b.ResetTimer()

View file

@ -14,6 +14,8 @@ type JSONLog struct {
Created time.Time `json:"time"`
// Attrs is the list of extra attributes provided by the user
Attrs map[string]string `json:"attrs,omitempty"`
// Tags requested the operator
Tag string `json:"tag,omitempty"`
}
// Reset all fields to their zero value.
@ -22,4 +24,5 @@ func (jl *JSONLog) Reset() {
jl.Stream = ""
jl.Created = time.Time{}
jl.Attrs = make(map[string]string)
jl.Tag = ""
}

View file

@ -12,6 +12,7 @@ type JSONLogs struct {
Log []byte `json:"log,omitempty"`
Stream string `json:"stream,omitempty"`
Created time.Time `json:"time"`
Tag string `json:"tag,omitempty"`
// json-encoded bytes
RawAttrs json.RawMessage `json:"attrs,omitempty"`
@ -37,6 +38,15 @@ func (mj *JSONLogs) MarshalJSONBuf(buf *bytes.Buffer) error {
buf.WriteString(`"stream":`)
ffjsonWriteJSONBytesAsString(buf, []byte(mj.Stream))
}
if len(mj.Tag) > 0 {
if first {
first = false
} else {
buf.WriteString(`,`)
}
buf.WriteString(`"tag":`)
ffjsonWriteJSONBytesAsString(buf, []byte(mj.Tag))
}
if len(mj.RawAttrs) > 0 {
if first {
first = false

View file

@ -29,6 +29,8 @@ func TestJSONLogsMarshalJSONBuf(t *testing.T) {
{Log: []byte{0x7F}}: `^{\"log\":\"\x7f\",\"time\":`,
// with raw attributes
{Log: []byte("A log line"), RawAttrs: []byte(`{"hello":"world","value":1234}`)}: `^{\"log\":\"A log line\",\"attrs\":{\"hello\":\"world\",\"value\":1234},\"time\":`,
// with Tag set
{Log: []byte("A log line with tag"), Tag: "test-tag"}: `^{\"log\":\"A log line with tag\",\"tag\":\"test-tag\",\"time\":`,
}
for jsonLog, expression := range logs {
var buf bytes.Buffer

View file

@ -35,7 +35,7 @@ func BenchmarkJSONFileLoggerReadLogs(b *testing.B) {
}
buf := bytes.NewBuffer(nil)
require.NoError(b, marshalMessage(msg, nil, buf))
require.NoError(b, marshalMessage(msg, nil, buf, ""))
b.SetBytes(int64(buf.Len()))
b.ResetTimer()