Skip to content

Commit

Permalink
Revert "Differentiation between metric and resource attributes (#984)"
Browse files Browse the repository at this point in the history
This reverts commit 84af0d1
  • Loading branch information
mariomac committed Jul 5, 2024
1 parent 31e98da commit 67da14d
Show file tree
Hide file tree
Showing 10 changed files with 160 additions and 271 deletions.
42 changes: 20 additions & 22 deletions pkg/internal/export/attributes/attr_defs.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func getDefinitions(groups AttrGroups) map[Section]AttrReportGroup {
// attributes to be reported exclusively for prometheus exporters
var prometheusAttributes = AttrReportGroup{
Disabled: !promEnabled,
MetricAttributes: map[attr.Name]Default{
Attributes: map[attr.Name]Default{
attr.TargetInstance: true,
attr.ServiceNamespace: true,
},
Expand All @@ -52,7 +52,7 @@ func getDefinitions(groups AttrGroups) map[Section]AttrReportGroup {
// but Grafana Cloud takes it from the metric
var appAttributes = AttrReportGroup{
SubGroups: []*AttrReportGroup{&prometheusAttributes},
MetricAttributes: map[attr.Name]Default{
Attributes: map[attr.Name]Default{
attr.ServiceName: true,
attr.ServiceNamespace: true,
},
Expand All @@ -62,7 +62,7 @@ func getDefinitions(groups AttrGroups) map[Section]AttrReportGroup {
// kubernetes metadata is enabled
var networkKubeAttributes = AttrReportGroup{
Disabled: !kubeEnabled,
MetricAttributes: map[attr.Name]Default{
Attributes: map[attr.Name]Default{
attr.K8sSrcOwnerName: true,
attr.K8sSrcNamespace: true,
attr.K8sDstOwnerName: true,
Expand All @@ -85,7 +85,7 @@ func getDefinitions(groups AttrGroups) map[Section]AttrReportGroup {
// is defined
var networkCIDR = AttrReportGroup{
Disabled: !cidrEnabled,
MetricAttributes: map[attr.Name]Default{
Attributes: map[attr.Name]Default{
attr.DstCIDR: true,
attr.SrcCIDR: true,
},
Expand All @@ -95,7 +95,7 @@ func getDefinitions(groups AttrGroups) map[Section]AttrReportGroup {
// kubernetes metadata is enabled
var appKubeAttributes = AttrReportGroup{
Disabled: !kubeEnabled,
ResourceAttributes: map[attr.Name]Default{
Attributes: map[attr.Name]Default{
attr.K8sNamespaceName: true,
attr.K8sPodName: true,
attr.K8sDeploymentName: true,
Expand All @@ -111,24 +111,24 @@ func getDefinitions(groups AttrGroups) map[Section]AttrReportGroup {

var httpRoutes = AttrReportGroup{
Disabled: !groups.Has(GroupHTTPRoutes),
MetricAttributes: map[attr.Name]Default{
Attributes: map[attr.Name]Default{
attr.HTTPRoute: true,
},
}

var serverInfo = AttrReportGroup{
MetricAttributes: map[attr.Name]Default{
Attributes: map[attr.Name]Default{
attr.ClientAddr: Default(peerInfoEnabled),
},
}
var httpClientInfo = AttrReportGroup{
MetricAttributes: map[attr.Name]Default{
Attributes: map[attr.Name]Default{
attr.ServerAddr: true,
attr.ServerPort: true,
},
}
var grpcClientInfo = AttrReportGroup{
MetricAttributes: map[attr.Name]Default{
Attributes: map[attr.Name]Default{
attr.ServerAddr: true,
},
}
Expand All @@ -138,14 +138,14 @@ func getDefinitions(groups AttrGroups) map[Section]AttrReportGroup {
// via the deprecated BEYLA_METRICS_REPORT_TARGET config option
var deprecatedHTTPPath = AttrReportGroup{
Disabled: !groups.Has(GroupTarget),
MetricAttributes: map[attr.Name]Default{
Attributes: map[attr.Name]Default{
attr.HTTPUrlPath: true,
},
}

var httpCommon = AttrReportGroup{
SubGroups: []*AttrReportGroup{&httpRoutes, &deprecatedHTTPPath},
MetricAttributes: map[attr.Name]Default{
Attributes: map[attr.Name]Default{
attr.HTTPRequestMethod: true,
attr.HTTPResponseStatusCode: true,
attr.HTTPUrlPath: false,
Expand All @@ -154,7 +154,7 @@ func getDefinitions(groups AttrGroups) map[Section]AttrReportGroup {

// TODO: populate it with host resource attributes in https://opentelemetry.io/docs/specs/semconv/resource/host/
var hostAttributes = AttrReportGroup{
ResourceAttributes: map[attr.Name]Default{
Attributes: map[attr.Name]Default{
attr.HostName: true,
},
}
Expand All @@ -164,7 +164,7 @@ func getDefinitions(groups AttrGroups) map[Section]AttrReportGroup {
// TODO: attributes below are resource-level, but in App O11y we don't treat processes as resources,
// but applications. Let's first consider how to match processes and Applications before marking this spec
// as stable
MetricAttributes: map[attr.Name]Default{
Attributes: map[attr.Name]Default{
attr.ProcCommand: true,
attr.ProcCPUState: true,
attr.ProcOwner: true,
Expand All @@ -181,7 +181,7 @@ func getDefinitions(groups AttrGroups) map[Section]AttrReportGroup {

var messagingAttributes = AttrReportGroup{
SubGroups: []*AttrReportGroup{&appAttributes, &appKubeAttributes},
MetricAttributes: map[attr.Name]Default{
Attributes: map[attr.Name]Default{
attr.MessagingSystem: true,
attr.MessagingDestination: true,
},
Expand All @@ -190,7 +190,7 @@ func getDefinitions(groups AttrGroups) map[Section]AttrReportGroup {
return map[Section]AttrReportGroup{
BeylaNetworkFlow.Section: {
SubGroups: []*AttrReportGroup{&networkCIDR, &networkKubeAttributes},
MetricAttributes: map[attr.Name]Default{
Attributes: map[attr.Name]Default{
attr.BeylaIP: false,
attr.Transport: false,
attr.SrcAddress: false,
Expand All @@ -217,15 +217,15 @@ func getDefinitions(groups AttrGroups) map[Section]AttrReportGroup {
},
RPCClientDuration.Section: {
SubGroups: []*AttrReportGroup{&appAttributes, &appKubeAttributes, &grpcClientInfo},
MetricAttributes: map[attr.Name]Default{
Attributes: map[attr.Name]Default{
attr.RPCMethod: true,
attr.RPCSystem: true,
attr.RPCGRPCStatusCode: true,
},
},
RPCServerDuration.Section: {
SubGroups: []*AttrReportGroup{&appAttributes, &appKubeAttributes, &serverInfo},
MetricAttributes: map[attr.Name]Default{
Attributes: map[attr.Name]Default{
attr.RPCMethod: true,
attr.RPCSystem: true,
attr.RPCGRPCStatusCode: true,
Expand All @@ -236,7 +236,7 @@ func getDefinitions(groups AttrGroups) map[Section]AttrReportGroup {
},
DBClientDuration.Section: {
SubGroups: []*AttrReportGroup{&appAttributes, &appKubeAttributes},
MetricAttributes: map[attr.Name]Default{
Attributes: map[attr.Name]Default{
attr.DBOperation: true,
attr.DBSystem: true,
attr.ErrorType: true,
Expand All @@ -249,7 +249,7 @@ func getDefinitions(groups AttrGroups) map[Section]AttrReportGroup {
SubGroups: []*AttrReportGroup{&messagingAttributes},
},
Traces.Section: {
MetricAttributes: map[attr.Name]Default{
Attributes: map[attr.Name]Default{
attr.DBQueryText: false,
},
},
Expand All @@ -268,9 +268,7 @@ func AllAttributeNames() map[attr.Name]struct{} {
names := map[attr.Name]struct{}{}
// -1 to enable all the metric group flags
for _, section := range getDefinitions(-1) {
allNames := section.All()
maps.Copy(names, allNames.Metric)
maps.Copy(names, allNames.Resource)
maps.Copy(names, section.All())
}
return names
}
19 changes: 5 additions & 14 deletions pkg/internal/export/attributes/attr_getters.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,16 @@ type NamedGetters[T, O any] func(name attr.Name) (Getter[T, O], bool)
// It differentiates two name formats: the exposed name for the attribute (uses _ for word separation, as
// required by Prometheus); and the internal name of the attribute (uses . for word separation, as internally Beyla
// stores the metadata).
func PrometheusGetters[T, O any](getter NamedGetters[T, O], names Sections[[]attr.Name]) []Field[T, O] {
// at the moment we will still keep prometheus attributes as metric-level
// TODO: move resource-level attributes to target_info metrics
attrNames := make([]attr.Name, 0, len(names.Metric)+len(names.Resource))
attrNames = append(attrNames, names.Metric...)
attrNames = append(attrNames, names.Resource...)
return buildGetterList(getter, attrNames, attr.Name.Prom)
func PrometheusGetters[T, O any](getter NamedGetters[T, O], names []attr.Name) []Field[T, O] {
return buildGetterList(getter, names, attr.Name.Prom)
}

// OpenTelemetryGetters builds a list of Getter getters for the names provided by the
// user configuration, ready to be passed to an OpenTelemetry exporter.
func OpenTelemetryGetters[T, O any](getter NamedGetters[T, O], names Sections[[]attr.Name]) Sections[[]Field[T, O]] {
otelToStr := func(name attr.Name) string {
func OpenTelemetryGetters[T, O any](getter NamedGetters[T, O], names []attr.Name) []Field[T, O] {
return buildGetterList(getter, names, func(name attr.Name) string {
return string(name.OTEL())
}
return Sections[[]Field[T, O]]{
Resource: buildGetterList(getter, names.Resource, otelToStr),
Metric: buildGetterList(getter, names.Metric, otelToStr),
}
})
}

func buildGetterList[T, O any](
Expand Down
108 changes: 31 additions & 77 deletions pkg/internal/export/attributes/attr_selector.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,8 @@ type AttrReportGroup struct {
// SubGroups are attribute groups related to this instance. If this instance is
// enabled, they might be also enabled (unless they are explicitly disabled)
SubGroups []*AttrReportGroup
// MetricAttributes map of name: enabled for this group. It refers to metric-level attributes.
MetricAttributes map[attr.Name]Default
// ResourceAttributes is like MetricAttributes but for resources (OTEL) or target_info (Prometheus)
ResourceAttributes map[attr.Name]Default
}

// Sections classifies some attribute-related groups between Metric and Resource attributes
type Sections[T any] struct {
Metric T
Resource T
// Attributes map of name: enabled for this group
Attributes map[attr.Name]Default
}

// AttrSelector returns, for each metric, the attributes that have to be reported
Expand All @@ -52,123 +44,85 @@ func NewAttrSelector(groups AttrGroups, selectorCfg Selection) (*AttrSelector, e
}

// For returns the list of enabled attribute names for a given metric
func (p *AttrSelector) For(metricName Name) Sections[[]attr.Name] {
func (p *AttrSelector) For(metricName Name) []attr.Name {
attributeNames, ok := p.definition[metricName.Section]
if !ok {
panic(fmt.Sprintf("BUG! metric not found %+v", metricName))
}
allInclusionLists := p.selector.Matching(metricName)
if len(allInclusionLists) == 0 {
attrs := attributeNames.Default()
// if the user did not provide any selector, return the default attributes for that metric
sas := Sections[[]attr.Name]{
Metric: helpers.SetToSlice(attrs.Metric),
Resource: helpers.SetToSlice(attrs.Resource),
}
slices.Sort(sas.Metric)
slices.Sort(sas.Resource)
return sas
}
matchingAttrs := Sections[map[attr.Name]struct{}]{
Metric: map[attr.Name]struct{}{},
Resource: map[attr.Name]struct{}{},
attrs := helpers.SetToSlice(attributeNames.Default())
slices.Sort(attrs)
return attrs
}
matchingAttrs := map[attr.Name]struct{}{}
for i, il := range allInclusionLists {
p.addIncludedAttributes(&matchingAttrs, attributeNames, il)
p.addIncludedAttributes(matchingAttrs, attributeNames, il)
// 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 {
if i == 0 && len(matchingAttrs) == 0 {
matchingAttrs = attributeNames.Default()
}
// now remove any attribute specified in the "exclude" lists
p.rmExcludedAttributes(&matchingAttrs, il)
p.rmExcludedAttributes(matchingAttrs, il)
}

sas := Sections[[]attr.Name]{
Metric: helpers.SetToSlice(matchingAttrs.Metric),
Resource: helpers.SetToSlice(matchingAttrs.Resource),
}
slices.Sort(sas.Metric)
slices.Sort(sas.Resource)
sas := helpers.SetToSlice(matchingAttrs)
slices.Sort(sas)
return sas
}

// 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{}],
matchingAttrs map[attr.Name]struct{},
attributeNames AttrReportGroup,
inclusionLists InclusionLists,
) {
allAttributes := attributeNames.All()
for attrName := range allAttributes.Metric {
for attrName := range allAttributes {
if inclusionLists.includes(attrName) {
matchingAttrs.Metric[attrName] = struct{}{}
}
}
for attrName := range allAttributes.Resource {
if inclusionLists.includes(attrName) {
matchingAttrs.Resource[attrName] = struct{}{}
matchingAttrs[attrName] = struct{}{}
}
}
}

func (p *AttrSelector) rmExcludedAttributes(matchingAttrs *Sections[map[attr.Name]struct{}], inclusionLists InclusionLists) {
maps.DeleteFunc(matchingAttrs.Metric, func(attr attr.Name, _ struct{}) bool {
return inclusionLists.excludes(attr)
})
maps.DeleteFunc(matchingAttrs.Resource, func(attr attr.Name, _ struct{}) bool {
func (p *AttrSelector) rmExcludedAttributes(matchingAttrs map[attr.Name]struct{}, inclusionLists InclusionLists) {
maps.DeleteFunc(matchingAttrs, func(attr attr.Name, _ struct{}) bool {
return inclusionLists.excludes(attr)
})
}

// All te attributes for this group and their subgroups, unless they are disabled.
func (p *AttrReportGroup) All() Sections[map[attr.Name]struct{}] {
sas := Sections[map[attr.Name]struct{}]{
Metric: map[attr.Name]struct{}{},
Resource: map[attr.Name]struct{}{},
}
func (p *AttrReportGroup) All() map[attr.Name]struct{} {
attrs := map[attr.Name]struct{}{}
if p.Disabled {
return sas
return attrs
}
for _, parent := range p.SubGroups {
psas := parent.All()
maps.Copy(sas.Metric, psas.Metric)
maps.Copy(sas.Resource, psas.Resource)
}
for k := range p.MetricAttributes {
sas.Metric[k] = struct{}{}
maps.Copy(attrs, parent.All())
}
for k := range p.ResourceAttributes {
sas.Resource[k] = struct{}{}
for k := range p.Attributes {
attrs[k] = struct{}{}
}
return sas
return attrs
}

// Default attributes for this group and their subgroups, unless they are disabled.
func (p *AttrReportGroup) Default() Sections[map[attr.Name]struct{}] {
sas := Sections[map[attr.Name]struct{}]{
Metric: map[attr.Name]struct{}{},
Resource: map[attr.Name]struct{}{},
}
func (p *AttrReportGroup) Default() map[attr.Name]struct{} {
attrs := map[attr.Name]struct{}{}
if p.Disabled {
return sas
return attrs
}
for _, parent := range p.SubGroups {
psas := parent.Default()
maps.Copy(sas.Metric, psas.Metric)
maps.Copy(sas.Resource, psas.Resource)
maps.Copy(attrs, parent.Default())
}
for k, def := range p.MetricAttributes {
for k, def := range p.Attributes {
if def {
sas.Metric[k] = struct{}{}
attrs[k] = struct{}{}
}
}
for k, def := range p.ResourceAttributes {
if def {
sas.Resource[k] = struct{}{}
}
}
return sas
return attrs
}
Loading

0 comments on commit 67da14d

Please sign in to comment.