Skip to content

Commit

Permalink
BCF-2636: add core node metrics path to service discovery (#10578)
Browse files Browse the repository at this point in the history
  • Loading branch information
krehermann authored Sep 11, 2023
1 parent 8cba02a commit 2e1014a
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 15 deletions.
29 changes: 17 additions & 12 deletions core/web/loop_registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,12 @@ func (l *LoopRegistryServer) discoveryHandler(w http.ResponseWriter, req *http.R
w.Header().Set("Content-Type", "application/json")
var groups []*targetgroup.Group

for _, registeredPlugin := range l.registry.List() {
// create a metric target for each running plugin
target := &targetgroup.Group{
Targets: []model.LabelSet{
// target address will be called by external prometheus
{model.AddressLabel: model.LabelValue(fmt.Sprintf("%s:%d", l.discoveryHostName, l.exposedPromPort))},
},
Labels: map[model.LabelName]model.LabelValue{
model.MetricsPathLabel: model.LabelValue(pluginMetricPath(registeredPlugin.Name)),
},
}
// add node metrics to service discovery
groups = append(groups, metricTarget(l.discoveryHostName, l.exposedPromPort, "/metrics"))

groups = append(groups, target)
// add all the plugins
for _, registeredPlugin := range l.registry.List() {
groups = append(groups, metricTarget(l.discoveryHostName, l.exposedPromPort, pluginMetricPath(registeredPlugin.Name)))
}

b, err := l.jsonMarshalFn(groups)
Expand All @@ -80,6 +73,18 @@ func (l *LoopRegistryServer) discoveryHandler(w http.ResponseWriter, req *http.R

}

func metricTarget(hostName string, port int, path string) *targetgroup.Group {
return &targetgroup.Group{
Targets: []model.LabelSet{
// target address will be called by external prometheus
{model.AddressLabel: model.LabelValue(fmt.Sprintf("%s:%d", hostName, port))},
},
Labels: map[model.LabelName]model.LabelValue{
model.MetricsPathLabel: model.LabelValue(path),
},
}
}

// pluginMetricHandlers routes from endpoints published in service discovery to the the backing LOOP endpoint
func (l *LoopRegistryServer) pluginMetricHandler(gc *gin.Context) {
pluginName := gc.Param("name")
Expand Down
37 changes: 34 additions & 3 deletions core/web/loop_registry_test.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package web_test

import (
"encoding/json"
"fmt"
"io"
"net/http"
"testing"

"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/prometheus/common/model"
"github.com/prometheus/prometheus/discovery/targetgroup"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/smartcontractkit/chainlink/v2/core/internal/cltest"
Expand Down Expand Up @@ -67,7 +71,13 @@ func TestLoopRegistry(t *testing.T) {
// shim a reference to the promserver that is running in our mock loop
// this ensures the client.Get calls below have a reference to mock loop impl

expectedEndPoint := "/plugins/mockLoopImpl/metrics"
expectedLooppEndPoint, expectedCoreEndPoint := "/plugins/mockLoopImpl/metrics", "/metrics"

// note we expect this to be an ordered result
expectedLabels := []model.LabelSet{
model.LabelSet{"__metrics_path__": model.LabelValue(expectedCoreEndPoint)},
model.LabelSet{"__metrics_path__": model.LabelValue(expectedLooppEndPoint)},
}

require.NoError(t, app.KeyStore.OCR().Add(cltest.DefaultOCRKey))
require.NoError(t, app.Start(testutils.Context(t)))
Expand Down Expand Up @@ -97,12 +107,22 @@ func TestLoopRegistry(t *testing.T) {
b, err := io.ReadAll(resp.Body)
require.NoError(t, err)
t.Logf("discovery response %s", b)
require.Contains(t, string(b), expectedEndPoint)
var got []*targetgroup.Group
require.NoError(t, json.Unmarshal(b, &got))

gotLabels := make([]model.LabelSet, 0)
for _, ls := range got {
gotLabels = append(gotLabels, ls.Labels)
}
assert.Equal(t, len(expectedLabels), len(gotLabels))
for i := range expectedLabels {
assert.EqualValues(t, expectedLabels[i], gotLabels[i])
}
})

t.Run("plugin metrics OK", func(t *testing.T) {
// plugin name `mockLoopImpl` matches key in PluginConfigs
resp, cleanup := client.Get(expectedEndPoint)
resp, cleanup := client.Get(expectedLooppEndPoint)
t.Cleanup(cleanup)
cltest.AssertServerResponse(t, resp, http.StatusOK)

Expand All @@ -117,6 +137,17 @@ func TestLoopRegistry(t *testing.T) {
require.Contains(t, string(b), expectedMetric)
})

t.Run("core metrics OK", func(t *testing.T) {
// core node metrics endpoint
resp, cleanup := client.Get(expectedCoreEndPoint)
t.Cleanup(cleanup)
cltest.AssertServerResponse(t, resp, http.StatusOK)

b, err := io.ReadAll(resp.Body)
require.NoError(t, err)
t.Logf("core metrics response %s", b)
})

t.Run("no existent plugin metrics ", func(t *testing.T) {
// request plugin that doesn't exist
resp, cleanup := client.Get("/plugins/noexist/metrics")
Expand Down

0 comments on commit 2e1014a

Please sign in to comment.