diff --git a/pkg/internal/export/attributes/attr_selector.go b/pkg/internal/export/attributes/attr_selector.go index fd5033bb9..860ee7356 100644 --- a/pkg/internal/export/attributes/attr_selector.go +++ b/pkg/internal/export/attributes/attr_selector.go @@ -73,18 +73,17 @@ func (p *AttrSelector) For(metricName Name) Sections[[]attr.Name] { Metric: map[attr.Name]struct{}{}, Resource: map[attr.Name]struct{}{}, } - for _, il := range allInclusionLists { + for i, il := range allInclusionLists { p.addIncludedAttributes(&matchingAttrs, attributeNames, il) - } - // if the "include" lists are empty, we use the default attributes - // as included - if len(matchingAttrs.Metric) == 0 && len(matchingAttrs.Resource) == 0 { - matchingAttrs = attributeNames.Default() - } - // now remove any attribute specified in the "exclude" lists - for _, il := range allInclusionLists { + // if the "include" lists are empty in the first iteration, we use the default attributes + // as included + if i == 0 && len(matchingAttrs.Metric) == 0 && len(matchingAttrs.Resource) == 0 { + matchingAttrs = attributeNames.Default() + } + // now remove any attribute specified in the "exclude" lists p.rmExcludedAttributes(&matchingAttrs, il) } + sas := Sections[[]attr.Name]{ Metric: helpers.SetToSlice(matchingAttrs.Metric), Resource: helpers.SetToSlice(matchingAttrs.Resource), @@ -94,7 +93,14 @@ func (p *AttrSelector) For(metricName Name) Sections[[]attr.Name] { return sas } -func (p *AttrSelector) addIncludedAttributes(matchingAttrs *Sections[map[attr.Name]struct{}], attributeNames AttrReportGroup, inclusionLists InclusionLists) { +// returns if the inclusion list have contents or not +// this will be useful to decide whether to use the default +// attribute set or not +func (p *AttrSelector) addIncludedAttributes( + matchingAttrs *Sections[map[attr.Name]struct{}], + attributeNames AttrReportGroup, + inclusionLists InclusionLists, +) { allAttributes := attributeNames.All() for attrName := range allAttributes.Metric { if inclusionLists.includes(attrName) { diff --git a/pkg/internal/export/attributes/attr_selector_test.go b/pkg/internal/export/attributes/attr_selector_test.go index 79e293281..e016a98b7 100644 --- a/pkg/internal/export/attributes/attr_selector_test.go +++ b/pkg/internal/export/attributes/attr_selector_test.go @@ -51,11 +51,13 @@ func TestFor_GlobEntries(t *testing.T) { p, err := NewAttrSelector(GroupKubernetes, Selection{ "*": InclusionLists{ Include: []string{"beyla_ip"}, - Exclude: []string{"k8s_*_name"}, + // won't be excluded from the final snapshot because they are + // re-included in the next inclusion list + Exclude: []string{"k8s_*_type"}, }, "beyla_network_flow_bytes_total": InclusionLists{ Include: []string{"src.*", "k8s.*"}, - Exclude: []string{"k8s.*.type"}, + Exclude: []string{"k8s.*.name"}, }, }) require.NoError(t, err) @@ -64,8 +66,12 @@ func TestFor_GlobEntries(t *testing.T) { "beyla.ip", "k8s.dst.namespace", "k8s.dst.node.ip", + "k8s.dst.owner.type", + "k8s.dst.type", "k8s.src.namespace", "k8s.src.node.ip", + "k8s.src.owner.type", + "k8s.src.type", "src.address", "src.name", "src.port", @@ -95,6 +101,52 @@ func TestFor_GlobEntries_NoInclusion(t *testing.T) { }, p.For(BeylaNetworkFlow)) } +func TestFor_GlobEntries_Order(t *testing.T) { + // verify that policies are overridden from more generic to more concrete + p, err := NewAttrSelector(0, Selection{ + "*": InclusionLists{ + Include: []string{"*"}, + }, + "beyla_network_*": InclusionLists{ + Exclude: []string{"dst.*", "transport", "direction", "iface"}, + }, + "beyla_network_flow_bytes_total": InclusionLists{ + Include: []string{"dst.name"}, + }, + }) + require.NoError(t, err) + assert.Equal(t, Sections[[]attr.Name]{ + Metric: []attr.Name{ + "beyla.ip", + "dst.name", + "src.address", + "src.name", + "src.port", + }, + Resource: []attr.Name{}, + }, p.For(BeylaNetworkFlow)) +} + +func TestFor_GlobEntries_Order_Default(t *testing.T) { + // verify that policies are overridden from more generic to more concrete + p, err := NewAttrSelector(0, Selection{ + "*": InclusionLists{}, // assuming default set + "http_*": InclusionLists{ + Exclude: []string{"*"}, + }, + "http_server_request_duration": InclusionLists{ + Include: []string{"url.path"}, + }, + }) + require.NoError(t, err) + assert.Equal(t, Sections[[]attr.Name]{ + Metric: []attr.Name{ + "url.path", + }, + Resource: []attr.Name{}, + }, p.For(HTTPServerDuration)) +} + func TestFor_KubeDisabled(t *testing.T) { p, err := NewAttrSelector(0, Selection{ "beyla_network_flow_bytes_total": InclusionLists{