Skip to content

Commit

Permalink
Add regex matching to resource attribute filters (#535)
Browse files Browse the repository at this point in the history
  • Loading branch information
damemi committed Nov 22, 2022
1 parent b101435 commit 97b3a35
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 5 deletions.
12 changes: 12 additions & 0 deletions exporter/collector/config.go
Expand Up @@ -18,6 +18,7 @@ import (
"context"
"errors"
"fmt"
"regexp"
"strings"
"time"

Expand Down Expand Up @@ -138,6 +139,8 @@ type ImpersonateConfig struct {
type ResourceFilter struct {
// Match resource keys by prefix
Prefix string `mapstructure:"prefix"`
// Match resource keys by regex
Regex string `mapstructure:"regex"`
}

type LogConfig struct {
Expand Down Expand Up @@ -185,6 +188,15 @@ func ValidateConfig(cfg Config) error {
}
seenReplacements[mapping.Replacement] = struct{}{}
}

for _, resourceFilter := range cfg.MetricConfig.ResourceFilters {
if len(resourceFilter.Regex) == 0 {
continue
}
if _, err := regexp.Compile(resourceFilter.Regex); err != nil {
return fmt.Errorf("unable to parse resource filter regex: %s", err.Error())
}
}
return nil
}

Expand Down
9 changes: 9 additions & 0 deletions exporter/collector/config_test.go
Expand Up @@ -66,6 +66,15 @@ func TestValidateConfig(t *testing.T) {
},
expectedErr: true,
},
{
desc: "Invalid resource filter regex",
input: Config{
MetricConfig: MetricConfig{
ResourceFilters: []ResourceFilter{{Regex: "*"}},
},
},
expectedErr: true,
},
} {
t.Run(tc.desc, func(t *testing.T) {
err := ValidateConfig(tc.input)
Expand Down
2 changes: 1 addition & 1 deletion exporter/collector/logs.go
Expand Up @@ -211,7 +211,7 @@ func (l logMapper) createEntries(ld plog.Logs) ([]*logpb.LogEntry, error) {
for i := 0; i < ld.ResourceLogs().Len(); i++ {
rl := ld.ResourceLogs().At(i)
mr := defaultResourceToMonitoredResource(rl.Resource())
extraResourceLabels := resourceToLabels(rl.Resource(), false, l.cfg.LogConfig.ResourceFilters)
extraResourceLabels := resourceToLabels(rl.Resource(), false, l.cfg.LogConfig.ResourceFilters, l.obs.log)
projectID := l.cfg.ProjectID
// override project ID with gcp.project.id, if present
if projectFromResource, found := rl.Resource().Attributes().Get(resourcemapping.ProjectIDAttributeKey); found {
Expand Down
2 changes: 1 addition & 1 deletion exporter/collector/metrics.go
Expand Up @@ -174,7 +174,7 @@ func (me *MetricsExporter) PushMetrics(ctx context.Context, m pmetric.Metrics) e
for i := 0; i < rms.Len(); i++ {
rm := rms.At(i)
monitoredResource := me.cfg.MetricConfig.MapMonitoredResource(rm.Resource())
extraResourceLabels := resourceToLabels(rm.Resource(), me.cfg.MetricConfig.ServiceResourceLabels, me.cfg.MetricConfig.ResourceFilters)
extraResourceLabels := resourceToLabels(rm.Resource(), me.cfg.MetricConfig.ServiceResourceLabels, me.cfg.MetricConfig.ResourceFilters, me.obs.log)
projectID := me.cfg.ProjectID
// override project ID with gcp.project.id, if present
if projectFromResource, found := rm.Resource().Attributes().Get(resourcemapping.ProjectIDAttributeKey); found {
Expand Down
6 changes: 5 additions & 1 deletion exporter/collector/monitoredresource.go
Expand Up @@ -15,8 +15,11 @@
package collector

import (
"regexp"
"strings"

"go.uber.org/zap"

"go.opentelemetry.io/collector/pdata/pcommon"
semconv "go.opentelemetry.io/collector/semconv/v1.8.0"
monitoredrespb "google.golang.org/genproto/googleapis/api/monitoredres"
Expand Down Expand Up @@ -58,6 +61,7 @@ func resourceToLabels(
resource pcommon.Resource,
serviceResourceLabels bool,
resourceFilters []ResourceFilter,
log *zap.Logger,
) labels {
attrs := pcommon.NewMap()
resource.Attributes().Range(func(k string, v pcommon.Value) bool {
Expand All @@ -71,7 +75,7 @@ func resourceToLabels(
}
// Matches one of the resource filters
for _, resourceFilter := range resourceFilters {
if strings.HasPrefix(k, resourceFilter.Prefix) {
if match, _ := regexp.Match(resourceFilter.Regex, []byte(k)); strings.HasPrefix(k, resourceFilter.Prefix) && match {
v.CopyTo(attrs.PutEmpty(k))
return true
}
Expand Down
25 changes: 23 additions & 2 deletions exporter/collector/monitoredresource_test.go
Expand Up @@ -456,6 +456,27 @@ func TestResourceToMetricLabels(t *testing.T) {
"service_namespace": "myservicenamespace",
},
},
{
name: "Resource filter regex config + prefix",
updateMapper: func(mapper *metricMapper) {
mapper.cfg.MetricConfig.ResourceFilters = []ResourceFilter{
{Prefix: "cloud.", Regex: ".*availability.*"},
{Regex: "host.*"},
}
},
resourceLabels: map[string]string{
"cloud.platform": "gcp_compute_engine",
"cloud.availability_zone": "us-central1",
"cloud.availability_region": "us-central",
"host.id": "abc123",
"random.fake": "woot",
},
expectExtraLabels: labels{
"cloud_availability_zone": "us-central1",
"cloud_availability_region": "us-central",
"host_id": "abc123",
},
},
}

for _, test := range tests {
Expand All @@ -468,7 +489,7 @@ func TestResourceToMetricLabels(t *testing.T) {
for k, v := range test.resourceLabels {
r.Attributes().PutStr(k, v)
}
extraLabels := resourceToLabels(r, mapper.cfg.MetricConfig.ServiceResourceLabels, mapper.cfg.MetricConfig.ResourceFilters)
extraLabels := resourceToLabels(r, mapper.cfg.MetricConfig.ServiceResourceLabels, mapper.cfg.MetricConfig.ResourceFilters, nil)
assert.Equal(t, test.expectExtraLabels, extraLabels)
})
}
Expand Down Expand Up @@ -516,6 +537,6 @@ func TestResourceMetricsToMonitoredResourceUTF8(t *testing.T) {
}
mr := defaultResourceToMonitoredResource(r)
assert.Equal(t, expectMr, mr)
extraLabels := resourceToLabels(r, mapper.cfg.MetricConfig.ServiceResourceLabels, mapper.cfg.MetricConfig.ResourceFilters)
extraLabels := resourceToLabels(r, mapper.cfg.MetricConfig.ServiceResourceLabels, mapper.cfg.MetricConfig.ResourceFilters, nil)
assert.Equal(t, expectExtraLabels, extraLabels)
}

0 comments on commit 97b3a35

Please sign in to comment.