diff --git a/CHANGELOG-developer.asciidoc b/CHANGELOG-developer.asciidoc index 74aecefbad1c..e575d97110f6 100644 --- a/CHANGELOG-developer.asciidoc +++ b/CHANGELOG-developer.asciidoc @@ -45,3 +45,4 @@ The list below covers the major changes between 6.3.0 and master only. coverage profile (.cov), and produces an HTML coverage report. See `mage -h goTestUnit`. {pull}7766[7766] - Beats packaging now build non-oss binaries from code located in the x-pack folder. {issue}7783[7783] +- New function `AddTagsWithKey` is added, so `common.MapStr` can be enriched with tags with an arbitrary key. {pull}7991[7991] diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index d04b8c03f39d..6b2827debab3 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -104,6 +104,7 @@ https://github.com/elastic/beats/compare/v6.4.0...master[Check the HEAD diff] - Add custom unpack to log hints config to avoid env resolution {pull}7710[7710] - Keep raw user agent information after parsing as user_agent_raw in Filebeat modules. {pull}7823[7832] - Make docker input check if container strings are empty {pull}7960[7960] +- Add tag "truncated" to "log.flags" if incoming line is longer than configured limit. {pull}7991[7991] *Heartbeat* diff --git a/filebeat/_meta/fields.common.yml b/filebeat/_meta/fields.common.yml index 5781e4978792..930e0f67f906 100644 --- a/filebeat/_meta/fields.common.yml +++ b/filebeat/_meta/fields.common.yml @@ -108,6 +108,10 @@ description: > Logging level. + - name: log.flags + description: > + This field contains the flags of the event. + - name: event.created type: date description: > diff --git a/filebeat/docs/fields.asciidoc b/filebeat/docs/fields.asciidoc index 4f5ec70dcbab..cb2e5e3b6100 100644 --- a/filebeat/docs/fields.asciidoc +++ b/filebeat/docs/fields.asciidoc @@ -2682,6 +2682,14 @@ type: keyword Logging level. +-- + +*`log.flags`*:: ++ +-- +This field contains the flags of the event. + + -- *`event.created`*:: diff --git a/filebeat/include/fields.go b/filebeat/include/fields.go index dabf266ec497..9de34e5d3b7b 100644 --- a/filebeat/include/fields.go +++ b/filebeat/include/fields.go @@ -31,5 +31,5 @@ func init() { // Asset returns asset data func Asset() string { - return "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" + return "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" } diff --git a/filebeat/reader/message.go b/filebeat/reader/message.go index c5e965b10d04..a92bc9092ccf 100644 --- a/filebeat/reader/message.go +++ b/filebeat/reader/message.go @@ -49,13 +49,28 @@ func (m *Message) IsEmpty() bool { return false } -func (msg *Message) AddFields(fields common.MapStr) { +// AddFields adds fields to the message. +func (m *Message) AddFields(fields common.MapStr) { if fields == nil { return } - if msg.Fields == nil { - msg.Fields = common.MapStr{} + if m.Fields == nil { + m.Fields = common.MapStr{} } - msg.Fields.Update(fields) + m.Fields.Update(fields) +} + +// AddFlagsWithKey adds flags to the message with an arbitrary key. +// If the field does not exist, it is created. +func (m *Message) AddFlagsWithKey(key string, flags ...string) error { + if len(flags) == 0 { + return nil + } + + if m.Fields == nil { + m.Fields = common.MapStr{} + } + + return common.AddTagsWithKey(m.Fields, key, flags) } diff --git a/filebeat/reader/multiline/multiline.go b/filebeat/reader/multiline/multiline.go index 57209be94cdc..2e974c19b235 100644 --- a/filebeat/reader/multiline/multiline.go +++ b/filebeat/reader/multiline/multiline.go @@ -48,6 +48,7 @@ type Reader struct { separator []byte last []byte numLines int + truncated int err error // last seen error state func(*Reader) (reader.Message, error) message reader.Message @@ -262,13 +263,19 @@ func (mlr *Reader) clear() { mlr.message = reader.Message{} mlr.last = nil mlr.numLines = 0 + mlr.truncated = 0 mlr.err = nil } // finalize writes the existing content into the returned message and resets all reader variables. func (mlr *Reader) finalize() reader.Message { + if mlr.truncated > 0 { + mlr.message.AddFlagsWithKey("log.flags", "truncated") + } + // Copy message from existing content msg := mlr.message + mlr.clear() return msg } @@ -303,6 +310,16 @@ func (mlr *Reader) addLine(m reader.Message) { } mlr.message.Content = append(tmp, m.Content[:space]...) mlr.numLines++ + + // add number of truncated bytes to fields + diff := len(m.Content) - space + if diff > 0 { + mlr.truncated += diff + } + } else { + // increase the number of skipped bytes, if cannot add + mlr.truncated += len(m.Content) + } mlr.last = m.Content diff --git a/filebeat/reader/multiline/multiline_test.go b/filebeat/reader/multiline/multiline_test.go index 6fe05fde0d28..1c6ea96c6f38 100644 --- a/filebeat/reader/multiline/multiline_test.go +++ b/filebeat/reader/multiline/multiline_test.go @@ -150,6 +150,41 @@ func TestMultilineBeforeNegateOKWithEmptyLine(t *testing.T) { ) } +func TestMultilineAfterTruncated(t *testing.T) { + pattern := match.MustCompile(`^[ ]`) // next line is indented a space + maxLines := 2 + testMultilineTruncated(t, + Config{ + Pattern: &pattern, + Match: "after", + MaxLines: &maxLines, + }, + 2, + true, + []string{ + "line1\n line1.1\n line1.2\n", + "line2\n line2.1\n line2.2\n"}, + []string{ + "line1\n line1.1", + "line2\n line2.1"}, + ) + testMultilineTruncated(t, + Config{ + Pattern: &pattern, + Match: "after", + MaxLines: &maxLines, + }, + 2, + false, + []string{ + "line1\n line1.1\n", + "line2\n line2.1\n"}, + []string{ + "line1\n line1.1", + "line2\n line2.1"}, + ) +} + func testMultilineOK(t *testing.T, cfg Config, events int, expected ...string) { _, buf := createLineBuffer(expected...) r := createMultilineTestReader(t, buf, cfg) @@ -177,6 +212,54 @@ func testMultilineOK(t *testing.T, cfg Config, events int, expected ...string) { } } +func testMultilineTruncated(t *testing.T, cfg Config, events int, truncated bool, input, expected []string) { + _, buf := createLineBuffer(input...) + r := createMultilineTestReader(t, buf, cfg) + + var messages []reader.Message + for { + message, err := r.Next() + if err != nil { + break + } + + messages = append(messages, message) + } + + if len(messages) != events { + t.Fatalf("expected %v lines, read only %v line(s)", len(expected), len(messages)) + } + + for _, message := range messages { + found := false + statusFlags, err := message.Fields.GetValue("log.flags") + if err != nil { + if !truncated { + assert.False(t, found) + return + } + t.Fatalf("error while getting log.status field: %v", err) + } + + switch flags := statusFlags.(type) { + case []string: + for _, f := range flags { + if f == "truncated" { + found = true + } + } + default: + t.Fatalf("incorrect type for log.flags") + } + + if truncated { + assert.True(t, found) + } else { + assert.False(t, found) + } + } +} + func createMultilineTestReader(t *testing.T, in *bytes.Buffer, cfg Config) reader.Reader { encFactory, ok := encoding.FindEncoding("plain") if !ok { diff --git a/filebeat/reader/readfile/limit.go b/filebeat/reader/readfile/limit.go index 1d7b46e2a471..42f9635ba124 100644 --- a/filebeat/reader/readfile/limit.go +++ b/filebeat/reader/readfile/limit.go @@ -38,6 +38,7 @@ func (r *LimitReader) Next() (reader.Message, error) { message, err := r.reader.Next() if len(message.Content) > r.maxBytes { message.Content = message.Content[:r.maxBytes] + message.AddFlagsWithKey("log.flags", "truncated") } return message, err } diff --git a/filebeat/reader/readfile/limit_test.go b/filebeat/reader/readfile/limit_test.go new file mode 100644 index 000000000000..c7096cb938f3 --- /dev/null +++ b/filebeat/reader/readfile/limit_test.go @@ -0,0 +1,88 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// +build !integration + +package readfile + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/elastic/beats/filebeat/reader" +) + +type mockReader struct { + line []byte +} + +func (m *mockReader) Next() (reader.Message, error) { + return reader.Message{ + Content: m.line, + }, nil +} + +var limitTests = []struct { + line string + maxBytes int + truncated bool +}{ + {"long-long-line", 5, true}, + {"long-long-line", 3, true}, + {"long-long-line", len("long-long-line"), false}, +} + +func TestLimitReader(t *testing.T) { + for _, test := range limitTests { + r := NewLimitReader(&mockReader{[]byte(test.line)}, test.maxBytes) + + msg, err := r.Next() + if err != nil { + t.Fatalf("Error reading from mock reader: %v", err) + } + + assert.Equal(t, test.maxBytes, len(msg.Content)) + + found := false + statusFlags, err := msg.Fields.GetValue("log.flags") + if err != nil { + if !test.truncated { + assert.False(t, found) + return + } + t.Fatalf("Error getting truncated value: %v", err) + } + + switch flags := statusFlags.(type) { + case []string: + for _, f := range flags { + if f == "truncated" { + found = true + } + } + default: + t.Fatalf("incorrect type for log.flags") + } + + if test.truncated { + assert.True(t, found) + } else { + assert.False(t, found) + } + } +} diff --git a/libbeat/common/mapstr.go b/libbeat/common/mapstr.go index 0bc2d4b2a161..2b825fd67e39 100644 --- a/libbeat/common/mapstr.go +++ b/libbeat/common/mapstr.go @@ -305,25 +305,38 @@ func MergeFields(ms, fields MapStr, underRoot bool) error { // exist then it will be created. If the tags field exists and is not a []string // then an error will be returned. It does not deduplicate the list of tags. func AddTags(ms MapStr, tags []string) error { + return AddTagsWithKey(ms, TagsKey, tags) +} + +// AddTagsWithKey appends a tag to the key field of ms. If the field does not +// exist then it will be created. If the field exists and is not a []string +// then an error will be returned. It does not deduplicate the list. +func AddTagsWithKey(ms MapStr, key string, tags []string) error { if ms == nil || len(tags) == 0 { return nil } - eventTags, exists := ms[TagsKey] - if !exists { - ms[TagsKey] = tags + + k, subMap, oldTags, present, err := mapFind(key, ms, true) + if err != nil { + return err + } + + if !present { + subMap[k] = tags return nil } - switch arr := eventTags.(type) { + switch arr := oldTags.(type) { case []string: - ms[TagsKey] = append(arr, tags...) + subMap[k] = append(arr, tags...) case []interface{}: for _, tag := range tags { arr = append(arr, tag) } - ms[TagsKey] = arr + subMap[k] = arr default: - return errors.Errorf("expected string array by type is %T", eventTags) + return errors.Errorf("expected string array by type is %T", oldTags) + } return nil } diff --git a/libbeat/common/mapstr_test.go b/libbeat/common/mapstr_test.go index 9002e5dfe03c..bb582c53b761 100644 --- a/libbeat/common/mapstr_test.go +++ b/libbeat/common/mapstr_test.go @@ -546,6 +546,79 @@ func TestAddTag(t *testing.T) { } } +func TestAddTagsWithKey(t *testing.T) { + type io struct { + Event MapStr + Key string + Tags []string + Output MapStr + Err string + } + tests := []io{ + // No existing tags, creates new tag array + { + Event: MapStr{}, + Key: "tags", + Tags: []string{"json"}, + Output: MapStr{ + "tags": []string{"json"}, + }, + }, + // Existing tags is a []string, appends + { + Event: MapStr{ + "tags": []string{"json"}, + }, + Key: "tags", + Tags: []string{"docker"}, + Output: MapStr{ + "tags": []string{"json", "docker"}, + }, + }, + // Existing tags are in submap and is a []interface{}, appends + { + Event: MapStr{ + "log": MapStr{ + "flags": []interface{}{"json"}, + }, + }, + Key: "log.flags", + Tags: []string{"docker"}, + Output: MapStr{ + "log": MapStr{ + "flags": []interface{}{"json", "docker"}, + }, + }, + }, + // Existing tags are in a submap and is not a []string or []interface{} + { + Event: MapStr{ + "log": MapStr{ + "flags": "not a slice", + }, + }, + Key: "log.flags", + Tags: []string{"docker"}, + Output: MapStr{ + "log": MapStr{ + "flags": "not a slice", + }, + }, + Err: "expected string array", + }, + } + + for _, test := range tests { + err := AddTagsWithKey(test.Event, test.Key, test.Tags) + assert.Equal(t, test.Output, test.Event) + if test.Err != "" { + assert.Contains(t, err.Error(), test.Err) + } else { + assert.NoError(t, err) + } + } +} + func TestFlatten(t *testing.T) { type data struct { Event MapStr