Skip to content

Commit

Permalink
[mdatagen] allow filtering out metrics based on resource attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
povilasv committed Feb 28, 2024
1 parent b808e85 commit d38c6b3
Show file tree
Hide file tree
Showing 19 changed files with 403 additions and 8 deletions.
25 changes: 25 additions & 0 deletions .chloggen/mdatagen-filter.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Use this changelog template to create an entry for release notes.

# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: enhancement

# The name of the component, or a single word describing the area of concern, (e.g. otlpreceiver)
component: "cmd/metadatagen"

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: "support excluding some metrics based on string and regexes in resource_attributes"

# One or more tracking issues or pull requests related to the change
issues: [9661]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext:

# Optional: The change log or logs in which this entry should be included.
# e.g. '[user]' or '[user, api]'
# Include 'user' if the change is relevant to end users.
# Include 'api' if there is a change to a library API.
# Default: '[user]'
change_logs: [user]
3 changes: 3 additions & 0 deletions cmd/mdatagen/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ require (
go.opentelemetry.io/collector/component v0.95.0
go.opentelemetry.io/collector/confmap v0.95.0
go.opentelemetry.io/collector/confmap/provider/fileprovider v0.95.0
go.opentelemetry.io/collector/filter v0.0.0-00010101000000-000000000000
go.opentelemetry.io/collector/pdata v1.2.0
go.opentelemetry.io/collector/receiver v0.95.0
go.opentelemetry.io/collector/semconv v0.95.0
Expand Down Expand Up @@ -70,6 +71,8 @@ replace go.opentelemetry.io/collector/featuregate => ../../featuregate

replace go.opentelemetry.io/collector/consumer => ../../consumer

replace go.opentelemetry.io/collector/filter => ../../filter

replace go.opentelemetry.io/collector => ../..

replace go.opentelemetry.io/collector/config/configtelemetry => ../../config/configtelemetry
Expand Down
5 changes: 4 additions & 1 deletion cmd/mdatagen/internal/metadata/generated_config.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion cmd/mdatagen/internal/metadata/generated_config_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

67 changes: 67 additions & 0 deletions cmd/mdatagen/internal/metadata/generated_metrics.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 2 additions & 3 deletions cmd/mdatagen/internal/metadata/generated_metrics_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions cmd/mdatagen/internal/metadata/generated_status.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions cmd/mdatagen/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

"go.opentelemetry.io/collector/confmap"
"go.opentelemetry.io/collector/confmap/provider/fileprovider"
"go.opentelemetry.io/collector/filter"
"go.opentelemetry.io/collector/pdata/pcommon"
)

Expand Down Expand Up @@ -156,6 +157,10 @@ type attribute struct {
NameOverride string `mapstructure:"name_override"`
// Enabled defines whether the attribute is enabled by default.
Enabled bool `mapstructure:"enabled"`
// Include can be used to filter attributes.
Include []filter.Config `mapstructure:"include"`
// Include can be used to filter attributes.
Exclude []filter.Config `mapstructure:"exclude"`
// Enum can optionally describe the set of values to which the attribute can belong.
Enum []string `mapstructure:"enum"`
// Type is an attribute type.
Expand Down
6 changes: 5 additions & 1 deletion cmd/mdatagen/templates/config.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ package {{ .Package }}
{{ if or .Metrics .ResourceAttributes -}}
import "go.opentelemetry.io/collector/confmap"
{{- end }}

{{ if .ResourceAttributes -}}
import "go.opentelemetry.io/collector/filter"
{{- end }}
{{ if .Metrics -}}

// MetricConfig provides common config for a particular metric.
Expand Down Expand Up @@ -49,6 +51,8 @@ func DefaultMetricsConfig() MetricsConfig {
// ResourceAttributeConfig provides common config for a particular resource attribute.
type ResourceAttributeConfig struct {
Enabled bool `mapstructure:"enabled"`
Include []filter.Config `mapstructure:"include"`
Exclude []filter.Config `mapstructure:"exclude"`

enabledSetByUser bool
}
Expand Down
35 changes: 35 additions & 0 deletions cmd/mdatagen/templates/metrics.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import (
{{- if .SemConvVersion }}
conventions "go.opentelemetry.io/collector/semconv/v{{ .SemConvVersion }}"
{{- end }}
{{ if .ResourceAttributes -}}
"go.opentelemetry.io/collector/filter"
{{- end }}
)

{{ range $name, $info := .Attributes }}
Expand Down Expand Up @@ -132,6 +135,10 @@ type MetricsBuilder struct {
metricsCapacity int // maximum observed number of metrics per resource.
metricsBuffer pmetric.Metrics // accumulates metrics data before emitting.
buildInfo component.BuildInfo // contains version information.
{{ if .ResourceAttributes -}}
resourceAttributeIncludeFilter map[string]filter.Filter
resourceAttributeExcludeFilter map[string]filter.Filter
{{- end }}
{{- range $name, $metric := .Metrics }}
metric{{ $name.Render }} metric{{ $name.Render }}
{{- end }}
Expand Down Expand Up @@ -190,7 +197,20 @@ func NewMetricsBuilder(mbc MetricsBuilderConfig, settings receiver.CreateSetting
{{- range $name, $metric := .Metrics }}
metric{{ $name.Render }}: newMetric{{ $name.Render }}(mbc.Metrics.{{ $name.Render }}),
{{- end }}
{{ if .ResourceAttributes -}}
resourceAttributeIncludeFilter: make(map[string]filter.Filter),
resourceAttributeExcludeFilter: make(map[string]filter.Filter),
{{- end }}
}
{{- range $name, $attr := .ResourceAttributes }}
if mbc.ResourceAttributes.{{ $name.Render }}.Include != nil {
mb.resourceAttributeIncludeFilter["{{ $name }}"] = filter.CreateFilter(mbc.ResourceAttributes.{{ $name.Render }}.Include)
}
if mbc.ResourceAttributes.{{ $name.Render }}.Exclude != nil {
mb.resourceAttributeExcludeFilter["{{ $name }}"] = filter.CreateFilter(mbc.ResourceAttributes.{{ $name.Render }}.Exclude)
}
{{- end }}

for _, op := range options {
op(mb)
}
Expand Down Expand Up @@ -263,6 +283,21 @@ func (mb *MetricsBuilder) EmitForResource(rmo ...ResourceMetricsOption) {
for _, op := range rmo {
op(rm)
}
{{ if .ResourceAttributes -}}
for name, val := range rm.Resource().Attributes().AsRaw() {
if filter, ok := mb.resourceAttributeIncludeFilter[name]; ok {
if !filter.Matches(val) {
return
}
}
if filter, ok := mb.resourceAttributeExcludeFilter[name]; ok {
if filter.Matches(val) {
return
}
}
}
{{- end }}

if ils.Metrics().Len() > 0 {
mb.updateCapacity(rm)
rm.MoveTo(mb.metricsBuffer.ResourceMetrics().AppendEmpty())
Expand Down
1 change: 1 addition & 0 deletions filter/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include ../Makefile.Common
72 changes: 72 additions & 0 deletions filter/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package filter // import "go.opentelemetry.io/collector/filter"

import (
"errors"
"regexp"
)

// Config configures the matching behavior of a FilterSet.
type Config struct {
Strict string `mapstructure:"strict"`
Regex string `mapstructure:"regexp"`
}

func (c Config) Validate() error {
if c.Strict == "" && c.Regex == "" {
return errors.New("must specify either strict or regex")
}
if c.Strict != "" && c.Regex != "" {
return errors.New("strict and regex cannot be used together")
}

if c.Regex != "" {
_, err := regexp.Compile(c.Regex)
if err != nil {
return err
}
}

return nil
}

type CombinedFilter struct {
stricts map[any]struct{}
regexes []*regexp.Regexp
}

// CreateFilter creates a Filter from yaml config.
func CreateFilter(configs []Config) Filter {
cf := &CombinedFilter{
stricts: make(map[any]struct{}),
}
for _, config := range configs {
if config.Strict != "" {
cf.stricts[config.Strict] = struct{}{}
}

if config.Regex != "" {
// Validate() call above ensures that the regex is valid.
re := regexp.MustCompile(config.Regex)
cf.regexes = append(cf.regexes, re)
}
}
return cf
}

func (cf *CombinedFilter) Matches(toMatch any) bool {
_, ok := cf.stricts[toMatch]
if ok {
return ok
}
if str, ok := toMatch.(string); ok {
for _, re := range cf.regexes {
if re.MatchString(str) {
return true
}
}
}
return false
}
Loading

0 comments on commit d38c6b3

Please sign in to comment.