diff --git a/agent/hcp/client/client.go b/agent/hcp/client/client.go index 1c49fd792471..9e3990ad7f3b 100644 --- a/agent/hcp/client/client.go +++ b/agent/hcp/client/client.go @@ -6,12 +6,15 @@ package client import ( "context" "fmt" + "regexp" "strconv" + "strings" "time" httptransport "github.com/go-openapi/runtime/client" "github.com/go-openapi/strfmt" + "github.com/hashicorp/go-multierror" hcptelemetry "github.com/hashicorp/hcp-sdk-go/clients/cloud-consul-telemetry-gateway/preview/2023-04-14/client/consul_telemetry_service" hcpgnm "github.com/hashicorp/hcp-sdk-go/clients/cloud-global-network-manager-service/preview/2022-02-15/client/global_network_manager_service" gnmmod "github.com/hashicorp/hcp-sdk-go/clients/cloud-global-network-manager-service/preview/2022-02-15/models" @@ -329,3 +332,32 @@ func (t *TelemetryConfig) DefaultLabels(cfg config.CloudConfig) map[string]strin return labels } + +// FilterRegex returns a valid regex used to filter metrics. +// It will fail if there are 0 valid regex filters given. +func (t *TelemetryConfig) FilterRegex() (*regexp.Regexp, error) { + var mErr error + filters := t.MetricsConfig.Filters + validFilters := make([]string, 0, len(filters)) + for _, filter := range filters { + _, err := regexp.Compile(filter) + if err != nil { + mErr = multierror.Append(mErr, fmt.Errorf("compilation of filter %q failed: %w", filter, err)) + continue + } + validFilters = append(validFilters, filter) + } + + if len(validFilters) == 0 { + return nil, multierror.Append(mErr, fmt.Errorf("no valid filters")) + } + + // Combine the valid regex strings with an OR. + finalRegex := strings.Join(validFilters, "|") + composedRegex, err := regexp.Compile(finalRegex) + if err != nil { + return nil, fmt.Errorf("failed to compile regex: %w", err) + } + + return composedRegex, nil +} diff --git a/agent/hcp/client/client_test.go b/agent/hcp/client/client_test.go index 0292fa3fab22..8587b0cfec89 100644 --- a/agent/hcp/client/client_test.go +++ b/agent/hcp/client/client_test.go @@ -199,3 +199,60 @@ func Test_DefaultLabels(t *testing.T) { }) } } + +func TestFilterRegex(t *testing.T) { + t.Parallel() + for name, tc := range map[string]struct { + filters []string + expectedRegexString string + matches []string + wantErr string + wantMatch bool + }{ + "badFilterRegex": { + filters: []string{"(*LF)"}, + wantErr: "no valid filters", + }, + "failsWithNoRegex": { + filters: []string{}, + wantErr: "no valid filters", + }, + "matchFound": { + filters: []string{"raft.*", "mem.*"}, + expectedRegexString: "raft.*|mem.*", + matches: []string{"consul.raft.peers", "consul.mem.heap_size"}, + wantMatch: true, + }, + "matchNotFound": { + filters: []string{"mem.*"}, + matches: []string{"consul.raft.peers", "consul.txn.apply"}, + expectedRegexString: "mem.*", + wantMatch: false, + }, + } { + tc := tc + t.Run(name, func(t *testing.T) { + t.Parallel() + cfg := &TelemetryConfig{ + MetricsConfig: &MetricsConfig{ + Filters: tc.filters, + }, + } + + f, err := cfg.FilterRegex() + + if tc.wantErr != "" { + require.Error(t, err) + require.Contains(t, err.Error(), tc.wantErr) + return + } + + require.NoError(t, err) + require.Equal(t, tc.expectedRegexString, f.String()) + for _, metric := range tc.matches { + m := f.MatchString(metric) + require.Equal(t, tc.wantMatch, m) + } + }) + } +} diff --git a/agent/hcp/telemetry/filter.go b/agent/hcp/telemetry/filter.go deleted file mode 100644 index 54dca7d44aef..000000000000 --- a/agent/hcp/telemetry/filter.go +++ /dev/null @@ -1,37 +0,0 @@ -package telemetry - -import ( - "fmt" - "regexp" - "strings" - - "github.com/hashicorp/go-multierror" -) - -// newFilterRegex returns a valid regex used to filter metrics. -// It will fail if there are 0 valid regex filters given. -func newFilterRegex(filters []string) (*regexp.Regexp, error) { - var mErr error - validFilters := make([]string, 0, len(filters)) - for _, filter := range filters { - _, err := regexp.Compile(filter) - if err != nil { - mErr = multierror.Append(mErr, fmt.Errorf("compilation of filter %q failed: %w", filter, err)) - continue - } - validFilters = append(validFilters, filter) - } - - if len(validFilters) == 0 { - return nil, multierror.Append(mErr, fmt.Errorf("no valid filters")) - } - - // Combine the valid regex strings with an OR. - finalRegex := strings.Join(validFilters, "|") - composedRegex, err := regexp.Compile(finalRegex) - if err != nil { - return nil, fmt.Errorf("failed to compile regex: %w", err) - } - - return composedRegex, nil -} diff --git a/agent/hcp/telemetry/filter_test.go b/agent/hcp/telemetry/filter_test.go deleted file mode 100644 index abe962f4cd47..000000000000 --- a/agent/hcp/telemetry/filter_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package telemetry - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestFilter(t *testing.T) { - t.Parallel() - for name, tc := range map[string]struct { - filters []string - expectedRegexString string - matches []string - wantErr string - wantMatch bool - }{ - "badFilterRegex": { - filters: []string{"(*LF)"}, - wantErr: "no valid filters", - }, - "failsWithNoRegex": { - filters: []string{}, - wantErr: "no valid filters", - }, - "matchFound": { - filters: []string{"raft.*", "mem.*"}, - expectedRegexString: "raft.*|mem.*", - matches: []string{"consul.raft.peers", "consul.mem.heap_size"}, - wantMatch: true, - }, - "matchNotFound": { - filters: []string{"mem.*"}, - matches: []string{"consul.raft.peers", "consul.txn.apply"}, - expectedRegexString: "mem.*", - wantMatch: false, - }, - } { - tc := tc - t.Run(name, func(t *testing.T) { - t.Parallel() - f, err := newFilterRegex(tc.filters) - - if tc.wantErr != "" { - require.Error(t, err) - require.Contains(t, err.Error(), tc.wantErr) - return - } - - require.NoError(t, err) - require.Equal(t, tc.expectedRegexString, f.String()) - for _, metric := range tc.matches { - m := f.MatchString(metric) - require.Equal(t, tc.wantMatch, m) - } - }) - } -}