Skip to content

Commit

Permalink
refactor: Rename confusing metric to reference_api
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidNix authored May 13, 2023
2 parents d3dd907 + 16755cf commit cf1dab0
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 91 deletions.
7 changes: 3 additions & 4 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func Execute() {
registry.MustRegister(metrics.BuildStatic(cfg.Static.Gauges)...)

// Register reference rpc metrics
refMets := metrics.NewReferenceRPC()
refMets := metrics.NewHTTPRequest()
registry.MustRegister(refMets.Metrics()...)

// Register cosmos chain metrics
Expand Down Expand Up @@ -125,7 +125,7 @@ func logFatal(msg string, err error) {
os.Exit(1)
}

func buildCosmosJobs(cosmosMets *metrics.Cosmos, refMets *metrics.ReferenceRPC, cfg Config) (jobs []metrics.Job) {
func buildCosmosJobs(cosmosMets *metrics.Cosmos, refMets *metrics.ReferenceAPI, cfg Config) (jobs []metrics.Job) {
// TODO(nix): Need different rest clients per chain. This hack prevents > 1 chain.
var urls []url.URL
for _, rest := range cfg.Cosmos[0].Rest {
Expand All @@ -136,8 +136,7 @@ func buildCosmosJobs(cosmosMets *metrics.Cosmos, refMets *metrics.ReferenceRPC,
urls = append(urls, *u)
}

const rpcType = "cosmos"
restClient := cosmos.NewRestClient(metrics.NewFallbackClient(httpClient, refMets, rpcType, urls))
restClient := cosmos.NewRestClient(metrics.NewFallbackClient(httpClient, refMets, urls))

restJobs := cosmos.BuildRestJobs(cosmosMets, restClient, cfg.Cosmos)
jobs = append(jobs, toJobs(restJobs)...)
Expand Down
12 changes: 5 additions & 7 deletions metrics/fallback_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,14 @@ type FallbackClient struct {
httpDo func(req *http.Request) (*http.Response, error)
log *slog.Logger
metrics ClientMetrics
rpcType string
}

type ClientMetrics interface {
IncClientError(rpcType string, host url.URL, reason string)
IncAPIError(host url.URL, reason string)
// TODO(nix): Metrics for request counts. Latency histogram.
}

func NewFallbackClient(client *http.Client, metrics ClientMetrics, rpcType string, hosts []url.URL) *FallbackClient {
func NewFallbackClient(client *http.Client, metrics ClientMetrics, hosts []url.URL) *FallbackClient {
if len(hosts) == 0 {
panic("no hosts provided")
}
Expand All @@ -33,15 +32,14 @@ func NewFallbackClient(client *http.Client, metrics ClientMetrics, rpcType strin
httpDo: client.Do,
log: slog.Default(),
metrics: metrics,
rpcType: rpcType,
}
}

const unknownErrReason = "unknown"

func (c FallbackClient) Get(ctx context.Context, path string) (*http.Response, error) {
doGet := func(host url.URL) (*http.Response, error) {
log := c.log.With("host", host.Hostname(), "path", path, "rpc", c.rpcType)
log := c.log.With("host", host.Hostname(), "path", path, "method", http.MethodGet)
host.Path = path
req, err := http.NewRequestWithContext(ctx, http.MethodGet, host.String(), nil)
if err != nil {
Expand All @@ -58,7 +56,7 @@ func (c FallbackClient) Get(ctx context.Context, path string) (*http.Response, e
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
_ = resp.Body.Close()
log.Error("Response returned bad status code", "status", resp.StatusCode)
c.metrics.IncClientError(c.rpcType, host, strconv.Itoa(resp.StatusCode))
c.metrics.IncAPIError(host, strconv.Itoa(resp.StatusCode))
return nil, fmt.Errorf("%s: bad status code %d", req.URL, resp.StatusCode)
}
return resp, nil
Expand All @@ -85,5 +83,5 @@ func (c FallbackClient) recordErrMetric(host url.URL, err error) {
// Do not record when the process is shutting down.
return
}
c.metrics.IncClientError(c.rpcType, host, reason)
c.metrics.IncAPIError(host, reason)
}
17 changes: 7 additions & 10 deletions metrics/fallback_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,12 @@ import (

type mockClientMetrics struct {
IncClientErrCalls int
GotRPCType string
GotHost url.URL
GotErrMsg string
}

func (m *mockClientMetrics) IncClientError(rpcType string, host url.URL, errMsg string) {
func (m *mockClientMetrics) IncAPIError(host url.URL, errMsg string) {
m.IncClientErrCalls++
m.GotRPCType = rpcType
m.GotHost = host
m.GotErrMsg = errMsg
}
Expand All @@ -41,7 +39,7 @@ func TestFallbackClient_Get(t *testing.T) {
ctx := context.WithValue(context.Background(), dummy("test"), dummy("test"))

t.Run("happy path", func(t *testing.T) {
client := NewFallbackClient(&http.Client{}, nil, "test", urls)
client := NewFallbackClient(&http.Client{}, nil, urls)
client.log = nopLogger
require.NotNil(t, client.httpDo)

Expand All @@ -65,7 +63,7 @@ func TestFallbackClient_Get(t *testing.T) {

t.Run("fallback on error", func(t *testing.T) {
var metrics mockClientMetrics
client := NewFallbackClient(nil, &metrics, "test", urls)
client := NewFallbackClient(nil, &metrics, urls)
client.log = nopLogger

var callCount int
Expand All @@ -91,7 +89,7 @@ func TestFallbackClient_Get(t *testing.T) {

t.Run("fallback on bad status code", func(t *testing.T) {
var metrics mockClientMetrics
client := NewFallbackClient(nil, &metrics, "test", urls)
client := NewFallbackClient(nil, &metrics, urls)
client.log = nopLogger

var callCount int
Expand Down Expand Up @@ -119,7 +117,7 @@ func TestFallbackClient_Get(t *testing.T) {
t.Run("all errors", func(t *testing.T) {
r := rand.New(rand.NewSource(time.Now().UnixNano()))
var metrics mockClientMetrics
client := NewFallbackClient(nil, &metrics, "test", urls)
client := NewFallbackClient(nil, &metrics, urls)
client.log = nopLogger

var callCount int
Expand Down Expand Up @@ -154,7 +152,7 @@ func TestFallbackClient_Get(t *testing.T) {
{nil, &http.Response{StatusCode: http.StatusNotFound}, "404"},
} {
var metrics mockClientMetrics
client := NewFallbackClient(nil, &metrics, "test", []url.URL{{Host: "error.example.com"}})
client := NewFallbackClient(nil, &metrics, []url.URL{{Host: "error.example.com"}})
client.log = nopLogger

client.httpDo = func(req *http.Request) (*http.Response, error) {
Expand All @@ -167,15 +165,14 @@ func TestFallbackClient_Get(t *testing.T) {
//nolint
_, _ = client.Get(ctx, "")

require.Equal(t, "test", metrics.GotRPCType, tt)
require.Equal(t, "error.example.com", metrics.GotHost.Hostname(), tt)
require.Equal(t, tt.WantMsg, metrics.GotErrMsg, tt)
}
})

t.Run("context canceled error", func(t *testing.T) {
var metrics mockClientMetrics
client := NewFallbackClient(nil, &metrics, "test", []url.URL{{Host: "error.example.com"}})
client := NewFallbackClient(nil, &metrics, []url.URL{{Host: "error.example.com"}})
client.log = nopLogger

client.httpDo = func(req *http.Request) (*http.Response, error) {
Expand Down
5 changes: 4 additions & 1 deletion metrics/metrics.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package metrics

const (
namespace = "sl_exporter"
namespace = "sl_exporter"

// Subsystems
staticSubsystem = "static"
cosmosSubsystem = "cosmos"
cosmosValSubsystem = cosmosSubsystem + "_val"
refAPISubsystem = "reference_api"
)
35 changes: 35 additions & 0 deletions metrics/reference_api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package metrics

import (
"net/url"

"github.com/prometheus/client_golang/prometheus"
)

// ReferenceAPI records metrics for external http calls.
type ReferenceAPI struct {
errorCounter *prometheus.CounterVec
// TODO(nix): Count requests and histogram of latency.
}

func NewHTTPRequest() *ReferenceAPI {
return &ReferenceAPI{
errorCounter: prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: prometheus.BuildFQName(namespace, refAPISubsystem, "error_total"),
Help: "Number of errors encountered while making external calls to an API to gather reference data.",
},
[]string{"host", "reason"},
),
}
}

func (c ReferenceAPI) IncAPIError(host url.URL, reason string) {
c.errorCounter.WithLabelValues(host.Hostname(), reason).Inc()
}

func (c ReferenceAPI) Metrics() []prometheus.Collector {
return []prometheus.Collector{
c.errorCounter,
}
}
29 changes: 29 additions & 0 deletions metrics/reference_api_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package metrics

import (
"net/http/httptest"
"net/url"
"testing"

"github.com/prometheus/client_golang/prometheus"
"github.com/stretchr/testify/require"
)

func TestReferenceAPI_IncAPIError(t *testing.T) {
t.Parallel()

reg := prometheus.NewRegistry()
metrics := NewHTTPRequest()
reg.MustRegister(metrics.Metrics()[0])

u, err := url.Parse("http://test.example/should/not/be/used")
require.NoError(t, err)

metrics.IncAPIError(*u, "timeout")

h := metricsHandler(reg)
r := httptest.NewRecorder()
h.ServeHTTP(r, stubRequest)

require.Contains(t, r.Body.String(), `sl_exporter_reference_api_error_total{host="test.example",reason="timeout"} 1`)
}
36 changes: 0 additions & 36 deletions metrics/reference_rpc.go

This file was deleted.

33 changes: 0 additions & 33 deletions metrics/reference_rpc_test.go

This file was deleted.

0 comments on commit cf1dab0

Please sign in to comment.