Skip to content

Commit

Permalink
filterspan: allow span kind matching
Browse files Browse the repository at this point in the history
  • Loading branch information
tanner-bruce committed Apr 21, 2022
1 parent 6a91d13 commit 89d091c
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 9 deletions.
22 changes: 16 additions & 6 deletions internal/coreinternal/processor/filterconfig/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,30 +115,40 @@ type MatchProperties struct {
// A match occurs if the span's implementation library matches at least one item in this list.
// This is an optional field.
Libraries []InstrumentationLibrary `mapstructure:"libraries"`

// SpanKinds specify the list of items to match the span kind against.
// A match occurs if the span's span kind matches at least one item in this list.
SpanKinds []string `mapstructure:"span_kinds"`
}

var (
ErrMissingRequiredField = errors.New(`at least one of "attributes", "libraries", or "resources" field must be specified`)
ErrInvalidLogField = errors.New("services, span_names, and span_kinds are not valid for log records")
ErrMissingRequiredLogField = errors.New(`at least one of "log_names", "attributes", "libraries", "span_kinds", or "resources" field must be specified`)
)

// ValidateForSpans validates properties for spans.
func (mp *MatchProperties) ValidateForSpans() error {
if len(mp.LogNames) > 0 {
return errors.New("log_names 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`)
len(mp.Libraries) == 0 && len(mp.Resources) == 0 && len(mp.SpanKinds) == 0 {
return ErrMissingRequiredField
}

return nil
}

// ValidateForLogs validates properties for logs.
func (mp *MatchProperties) ValidateForLogs() error {
if len(mp.SpanNames) > 0 || len(mp.Services) > 0 {
return errors.New("neither services nor span_names should be specified for log records")
if len(mp.SpanNames) > 0 || len(mp.Services) > 0 || len(mp.SpanKinds) > 0 {
return ErrInvalidLogField
}

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

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

// Span names to compare to.
nameFilters filterset.FilterSet

// Span kinds to compare to
kindFilters filterset.FilterSet
}

// NewMatcher creates a span Matcher that matches based on the given MatchProperties.
Expand Down Expand Up @@ -75,10 +78,19 @@ func NewMatcher(mp *filterconfig.MatchProperties) (Matcher, error) {
}
}

var kindFS filterset.FilterSet
if len(mp.SpanKinds) > 0 {
kindFS, err = filterset.CreateFilterSet(mp.SpanKinds, &mp.Config)
if err != nil {
return nil, fmt.Errorf("error creating span kind filters: %v", err)
}
}

return &propertiesMatcher{
PropertiesMatcher: rm,
serviceFilters: serviceFS,
nameFilters: nameFS,
kindFilters: kindFS,
}, nil
}

Expand Down Expand Up @@ -121,6 +133,10 @@ func (mp *propertiesMatcher) MatchSpan(span pdata.Span, resource pdata.Resource,
return false
}

if mp.kindFilters != nil && !mp.kindFilters.Matches(span.Kind().String()) {
return false
}

return mp.PropertiesMatcher.Match(span.Attributes(), resource, library)
}

Expand Down
43 changes: 40 additions & 3 deletions internal/coreinternal/processor/filterspan/filterspan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@ func TestSpan_validateMatchesConfiguration_InvalidConfig(t *testing.T) {
{
name: "empty_property",
property: filterconfig.MatchProperties{},
errorString: "at least one of \"services\", \"span_names\", \"attributes\", \"libraries\" or \"resources\" field must be specified",
errorString: filterconfig.ErrMissingRequiredField.Error(),
},
{
name: "empty_service_span_names_and_attributes",
property: filterconfig.MatchProperties{
Services: []string{},
},
errorString: "at least one of \"services\", \"span_names\", \"attributes\", \"libraries\" or \"resources\" field must be specified",
errorString: filterconfig.ErrMissingRequiredField.Error(),
},
{
name: "log_properties",
Expand Down Expand Up @@ -112,7 +112,6 @@ func TestSpan_Matching_False(t *testing.T) {
Attributes: []filterconfig.Attribute{},
},
},

{
name: "service_name_doesnt_match_strict",
properties: &filterconfig.MatchProperties{
Expand Down Expand Up @@ -143,6 +142,23 @@ func TestSpan_Matching_False(t *testing.T) {
Attributes: []filterconfig.Attribute{},
},
},

{
name: "span_kind_doesnt_match_regexp",
properties: &filterconfig.MatchProperties{
Config: *createConfig(filterset.Regexp),
Attributes: []filterconfig.Attribute{},
SpanKinds: []string{pdata.SpanKindProducer.String()},
},
},
{
name: "span_kind_doesnt_match_strict",
properties: &filterconfig.MatchProperties{
Config: *createConfig(filterset.Strict),
Attributes: []filterconfig.Attribute{},
SpanKinds: []string{pdata.SpanKindProducer.String()},
},
},
}

span := pdata.NewSpan()
Expand Down Expand Up @@ -217,6 +233,26 @@ func TestSpan_Matching_True(t *testing.T) {
Attributes: []filterconfig.Attribute{},
},
},
{
name: "span_kind_match_strict",
properties: &filterconfig.MatchProperties{
Config: *createConfig(filterset.Strict),
SpanKinds: []string{
pdata.SpanKindClient.String(),
},
Attributes: []filterconfig.Attribute{},
},
},
{
name: "span_kind_match_regexp",
properties: &filterconfig.MatchProperties{
Config: *createConfig(filterset.Regexp),
SpanKinds: []string{
"CLIENT",
},
Attributes: []filterconfig.Attribute{},
},
},
}

span := pdata.NewSpan()
Expand All @@ -226,6 +262,7 @@ func TestSpan_Matching_True(t *testing.T) {
span.Attributes().InsertDouble("keyDouble", 3245.6)
span.Attributes().InsertBool("keyBool", true)
span.Attributes().InsertString("keyExists", "present")
span.SetKind(pdata.SpanKindClient)
assert.NotNil(t, span)

resource := pdata.NewResource()
Expand Down

0 comments on commit 89d091c

Please sign in to comment.