Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[attributesprocessor] Support filter by severity #9132

Merged
merged 3 commits into from
Apr 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
### 💡 Enhancements 💡
- `pkg/translator/prometheusremotewrite`: Allow to disable sanitize metric labels (#8270)

- `attributesprocessor`: Support filter by severity (#9132)

### 🧰 Bug fixes 🧰

## v0.49.0
Expand Down
12 changes: 10 additions & 2 deletions internal/coreinternal/processor/filterconfig/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ type MatchProperties struct {
// against.
LogBodies []string `mapstructure:"log_bodies"`

// LogSeverityTexts is a list of strings that the LogRecord's severity text field must match
// against.
LogSeverityTexts []string `mapstructure:"log_severity_texts"`

// MetricNames is a list of strings to match metric name against.
// A match occurs if metric name matches at least one item in the list.
// This field is optional.
Expand Down Expand Up @@ -122,6 +126,10 @@ func (mp *MatchProperties) ValidateForSpans() error {
return errors.New("log_bodies should not be specified for trace spans")
}

if len(mp.LogSeverityTexts) > 0 {
return errors.New("log_severity_texts should not be specified for trace spans")
}

if len(mp.Services) == 0 && len(mp.SpanNames) == 0 && len(mp.Attributes) == 0 &&
len(mp.Libraries) == 0 && len(mp.Resources) == 0 {
return errors.New(`at least one of "services", "span_names", "attributes", "libraries" or "resources" field must be specified`)
Expand All @@ -136,8 +144,8 @@ func (mp *MatchProperties) ValidateForLogs() error {
return errors.New("neither services nor span_names should be specified for log records")
}

if len(mp.Attributes) == 0 && len(mp.Libraries) == 0 && len(mp.Resources) == 0 && len(mp.LogBodies) == 0 {
return errors.New(`at least one of "attributes", "libraries", "resources" or "log_bodies" field must be specified`)
if len(mp.Attributes) == 0 && len(mp.Libraries) == 0 && len(mp.Resources) == 0 && len(mp.LogBodies) == 0 && len(mp.LogSeverityTexts) == 0 {
return errors.New(`at least one of "attributes", "libraries", "resources", "log_bodies" or "log_severity_texts" field must be specified`)
}

return nil
Expand Down
18 changes: 16 additions & 2 deletions internal/coreinternal/processor/filterlog/filterlog.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ type propertiesMatcher struct {

// log bodies to compare to.
bodyFilters filterset.FilterSet

// log severity texts to compare to
severityTextFilters filterset.FilterSet
}

// NewMatcher creates a LogRecord Matcher that matches based on the given MatchProperties.
Expand All @@ -63,10 +66,18 @@ func NewMatcher(mp *filterconfig.MatchProperties) (Matcher, error) {
return nil, fmt.Errorf("error creating log record body filters: %v", err)
}
}
var severitytextFS filterset.FilterSet
if len(mp.LogSeverityTexts) > 0 {
severitytextFS, err = filterset.CreateFilterSet(mp.LogSeverityTexts, &mp.Config)
if err != nil {
return nil, fmt.Errorf("error creating log record severity text filters: %v", err)
}
}

return &propertiesMatcher{
PropertiesMatcher: rm,
bodyFilters: bodyFS,
PropertiesMatcher: rm,
bodyFilters: bodyFS,
severityTextFilters: severitytextFS,
}, nil
}

Expand All @@ -82,6 +93,9 @@ func (mp *propertiesMatcher) MatchLogRecord(lr plog.LogRecord, resource pcommon.
if lr.Body().Type() == pcommon.ValueTypeString && mp.bodyFilters != nil && mp.bodyFilters.Matches(lr.Body().StringVal()) {
return true
}
if mp.severityTextFilters != nil && mp.severityTextFilters.Matches(lr.SeverityText()) {
return true
}

return mp.PropertiesMatcher.Match(lr.Attributes(), resource, library)
}
15 changes: 12 additions & 3 deletions internal/coreinternal/processor/filterlog/filterlog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,15 @@ func TestLogRecord_validateMatchesConfiguration_InvalidConfig(t *testing.T) {
{
name: "empty_property",
property: filterconfig.MatchProperties{},
errorString: `at least one of "attributes", "libraries", "resources" or "log_bodies" field must be specified`,
errorString: `at least one of "attributes", "libraries", "resources", "log_bodies" or "log_severity_texts" field must be specified`,
},
{
name: "empty_log_bodies_and_attributes",
property: filterconfig.MatchProperties{
LogBodies: []string{},
LogBodies: []string{},
LogSeverityTexts: []string{},
},
errorString: `at least one of "attributes", "libraries", "resources" or "log_bodies" field must be specified`,
errorString: `at least one of "attributes", "libraries", "resources", "log_bodies" or "log_severity_texts" field must be specified`,
},
{
name: "span_properties",
Expand Down Expand Up @@ -157,11 +158,19 @@ func TestLogRecord_Matching_True(t *testing.T) {
LogBodies: []string{"AUTH.*"},
},
},
{
name: "log_severity_text_regexp_match",
properties: &filterconfig.MatchProperties{
Config: *createConfig(filterset.Regexp),
LogSeverityTexts: []string{"debug.*"},
},
},
}

lr := plog.NewLogRecord()
lr.Attributes().InsertString("abc", "def")
lr.Body().SetStringVal("AUTHENTICATION FAILED")
lr.SetSeverityText("debug")

for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
Expand Down
10 changes: 7 additions & 3 deletions processor/attributesprocessor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,13 +166,13 @@ if the input data should be included or excluded from the processor. To configur
this option, under `include` and/or `exclude` at least `match_type` and one of the following
is required:
- For spans, one of `services`, `span_names`, `attributes`, `resources`, or `libraries` must be specified
with a non-empty value for a valid configuration. The `log_bodies`, `expressions`, `resource_attributes` and
with a non-empty value for a valid configuration. The `log_bodies`, `log_severity_texts`, `expressions`, `resource_attributes` and
`metric_names` fields are invalid.
- For logs, one of `log_bodies`, `attributes`, `resources`, or `libraries` must be specified with a
- For logs, one of `log_bodies`, `log_severity_texts`, `attributes`, `resources`, or `libraries` must be specified with a
non-empty value for a valid configuration. The `span_names`, `metric_names`, `expressions`, `resource_attributes`,
and `services` fields are invalid.
- For metrics, one of `metric_names`, `resources` must be specified
with a valid non-empty value for a valid configuration. The `span_names`, `log_bodies` and
with a valid non-empty value for a valid configuration. The `span_names`, `log_bodies`, `log_severity_texts` and
`services` fields are invalid.


Expand Down Expand Up @@ -219,6 +219,10 @@ attributes:
# This is an optional field.
log_bodies: [<item1>, ..., <itemN>]

# The log severity text must match at least one of the items.
# This is an optional field.
log_severity_texts: [<item1>, ..., <itemN>]

# The metric name must match at least one of the items.
# This is an optional field.
metric_names: [<item1>, ..., <itemN>]
Expand Down
17 changes: 17 additions & 0 deletions processor/attributesprocessor/testdata/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,23 @@ processors:
- key: token
action: delete

# The following demonstrates how to process logs that have a severity text that match regexp
# patterns. This processor will remove "token" attribute and will obfuscate "password"
# attribute in spans where severity matches "debug".
attributes/log_severity_regexp:
# Specifies the span properties that must exist for the processor to be applied.
include:
# match_type defines that "services" is an array of regexp-es.
match_type: regexp
# The log severity text "debug.*" pattern.
log_severity_texts: [ "debug.*" ]
actions:
- key: password
action: update
value: "obfuscated"
- key: token
action: delete

receivers:
nop:

Expand Down