From 1a77653affea84b4c59b1a7f90e4d0df124c34b0 Mon Sep 17 00:00:00 2001 From: Chris Berry Date: Tue, 15 Oct 2024 15:01:06 +0100 Subject: [PATCH] Standardise provider format --- CHANGELOG.md | 1 + services/metrics/prometheus/client.go | 43 ++++++++++++++++++++++ services/metrics/prometheus/client_test.go | 27 ++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 services/metrics/prometheus/client_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 38b4ed2c..8adb45e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ 1.9.1: - ensure that secondary validator registrations take place for all accounts - reduce the log level of successful sync committee duties + - standardise provider address format across client and strategy operations 1.9.0: - allow Vouch to start with some consensus nodes unavailable diff --git a/services/metrics/prometheus/client.go b/services/metrics/prometheus/client.go index 4a61c123..259bfd6b 100644 --- a/services/metrics/prometheus/client.go +++ b/services/metrics/prometheus/client.go @@ -15,6 +15,10 @@ package prometheus import ( "errors" + "fmt" + "net/url" + "regexp" + "strings" "time" "github.com/prometheus/client_golang/prometheus" @@ -97,6 +101,10 @@ func (s *Service) setupClientMetrics() error { // ClientOperation registers an operation. func (s *Service) ClientOperation(provider string, operation string, succeeded bool, duration time.Duration) { + address, err := parseAddress(provider) + if err == nil && address != nil { + provider = address.String() + } if succeeded { s.clientOperationCounter.WithLabelValues(provider, operation, "succeeded").Add(1) s.clientOperationTimer.WithLabelValues(provider, operation).Observe(duration.Seconds()) @@ -107,6 +115,41 @@ func (s *Service) ClientOperation(provider string, operation string, succeeded b // StrategyOperation provides a generic monitor for strategy operations. func (s *Service) StrategyOperation(strategy string, provider string, operation string, duration time.Duration) { + address, err := parseAddress(provider) + if err == nil && address != nil { + provider = address.String() + } s.strategyOperationCounter.WithLabelValues(strategy, provider, operation).Add(1) s.strategyOperationTimer.WithLabelValues(strategy, provider, operation).Observe(duration.Seconds()) } + +func parseAddress(address string) (*url.URL, error) { + if !strings.HasPrefix(address, "http") { + address = fmt.Sprintf("http://%s", address) + } + base, err := url.Parse(address) + if err != nil { + return nil, errors.Join(errors.New("invalid URL"), err) + } + // Remove any trailing slash from the path. + base.Path = strings.TrimSuffix(base.Path, "/") + + // Attempt to mask any sensitive information in the URL, for logging purposes. + baseAddress := *base + if _, pwExists := baseAddress.User.Password(); pwExists { + // Mask the password. + user := baseAddress.User.Username() + baseAddress.User = url.UserPassword(user, "xxxxx") + } + if baseAddress.Path != "" { + // Mask the path. + baseAddress.Path = "xxxxx" + } + if baseAddress.RawQuery != "" { + // Mask all query values. + sensitiveRegex := regexp.MustCompile("=([^&]*)(&)?") + baseAddress.RawQuery = sensitiveRegex.ReplaceAllString(baseAddress.RawQuery, "=xxxxx$2") + } + + return &baseAddress, nil +} diff --git a/services/metrics/prometheus/client_test.go b/services/metrics/prometheus/client_test.go new file mode 100644 index 00000000..09cddf0a --- /dev/null +++ b/services/metrics/prometheus/client_test.go @@ -0,0 +1,27 @@ +// Copyright © 2021 Attestant Limited. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package prometheus + +import ( + "github.com/stretchr/testify/require" + "testing" +) + +func TestParseAddress(t *testing.T) { + provider := "eth-val-d03-01.attestant.io:15100" + url, err := parseAddress(provider) + require.NoError(t, err) + require.Equal(t, "http://eth-val-d03-01.attestant.io:15100", url.String()) + +}