Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/multikey metrics #5362

Merged
merged 29 commits into from
Jul 11, 2023
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
e2f2899
fixed metrics which did not update for managed keys
sstanculeanu Jun 16, 2023
f8a1f1b
added managed peers monitor
sstanculeanu Jun 16, 2023
f779c1c
new API endpoints for managed keys
sstanculeanu Jun 19, 2023
66f5613
Merge pull request #5356 from multiversx/managed_peers_monitor
sstanculeanu Jun 20, 2023
85c9d3d
Merge branch 'feat/multikey_metrics' into update_metrics_for_managed_…
sstanculeanu Jun 20, 2023
52459de
fixes after review
sstanculeanu Jun 20, 2023
c3611bc
Merge branch 'feat/multikey_metrics' into new_endpoints
sstanculeanu Jun 20, 2023
73d5389
updated api.toml
sstanculeanu Jun 20, 2023
32f7133
fixes after review, now managed-keys endpoints return for current epo…
sstanculeanu Jun 20, 2023
561065c
Merge pull request #5357 from multiversx/new_endpoints
sstanculeanu Jun 20, 2023
729e925
Merge branch 'feat/multikey_metrics' into update_metrics_for_managed_…
sstanculeanu Jun 20, 2023
c2f41cb
Merge pull request #5354 from multiversx/update_metrics_for_managed_keys
sstanculeanu Jun 21, 2023
2eca865
Merge branch 'rc/v1.6.0' of https://github.com/multiversx/mx-chain-go…
sstanculeanu Jun 22, 2023
b27b180
Merge pull request #5369 from multiversx/merge_rc160_into_feat_multik…
sstanculeanu Jun 22, 2023
f8f00c6
fix after test, added missing initialization
sstanculeanu Jun 22, 2023
5811bad
Merge pull request #5371 from multiversx/fix_managedPeersHolder_initi…
sstanculeanu Jun 22, 2023
3d6a43c
new endpoint for all managed keys
sstanculeanu Jun 26, 2023
1cd3555
fixed return type
sstanculeanu Jun 26, 2023
93613ba
fix after review, sort keys
sstanculeanu Jun 26, 2023
d20e13e
update test
sstanculeanu Jun 26, 2023
a46e91f
Merge pull request #5375 from multiversx/all_managed_keys_endpoint
sstanculeanu Jun 26, 2023
1c554d3
Merge branch 'rc/v1.6.0' of https://github.com/multiversx/mx-chain-go…
sstanculeanu Jun 26, 2023
c54fdb2
Merge pull request #5377 from multiversx/merge_rc160_into_feat_multik…
sstanculeanu Jun 26, 2023
1ecc939
Merge branch 'rc/v1.6.0' of https://github.com/multiversx/mx-chain-go…
sstanculeanu Jul 7, 2023
cb8a589
Merge pull request #5412 from multiversx/merge_rc160_into_feat_multik…
sstanculeanu Jul 7, 2023
bd02864
Merge branch 'rc/v1.6.0' of https://github.com/multiversx/mx-chain-go…
sstanculeanu Jul 10, 2023
3296a9c
Merge pull request #5414 from multiversx/merge_rc160_into_feat_multik…
sstanculeanu Jul 10, 2023
f261b10
Merge branch 'rc/v1.6.0' of https://github.com/multiversx/mx-chain-go…
sstanculeanu Jul 11, 2023
b09daf1
Merge pull request #5420 from multiversx/merge_rc160_into_feat_multik…
sstanculeanu Jul 11, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions api/errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,3 +165,9 @@ var ErrInvalidRole = errors.New("invalid role")

// ErrIsDataTrieMigrated signals that an error occurred while trying to verify the migration status of the data trie
var ErrIsDataTrieMigrated = errors.New("could not verify the migration status of the data trie")

// ErrGetEligibleManagedKeys signals that an error occurred while getting the eligible managed keys
var ErrGetEligibleManagedKeys = errors.New("error getting the eligible managed keys")

// ErrGetWaitingManagedKeys signals that an error occurred while getting the waiting managed keys
var ErrGetWaitingManagedKeys = errors.New("error getting the waiting managed keys")
70 changes: 70 additions & 0 deletions api/groups/nodeGroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ const (
epochStartDataForEpoch = "/epoch-start/:epoch"
bootstrapStatusPath = "/bootstrapstatus"
connectedPeersRatingsPath = "/connected-peers-ratings"
managedKeysCount = "/managed-keys/count"
eligibleManagedKeys = "/managed-keys/eligible"
waitingManagedKeys = "/managed-keys/waiting"
)

// nodeFacadeHandler defines the methods to be implemented by a facade for node requests
Expand All @@ -37,6 +40,9 @@ type nodeFacadeHandler interface {
GetEpochStartDataAPI(epoch uint32) (*common.EpochStartDataAPI, error)
GetPeerInfo(pid string) ([]core.QueryP2PPeerInfo, error)
GetConnectedPeersRatings() string
GetManagedKeysCount() int
GetEligibleManagedKeys() ([]string, error)
GetWaitingManagedKeys() ([]string, error)
IsInterfaceNil() bool
}

Expand Down Expand Up @@ -109,6 +115,21 @@ func NewNodeGroup(facade nodeFacadeHandler) (*nodeGroup, error) {
Method: http.MethodGet,
Handler: ng.connectedPeersRatings,
},
{
Path: managedKeysCount,
Method: http.MethodGet,
Handler: ng.managedKeysCount,
},
{
Path: eligibleManagedKeys,
Method: http.MethodGet,
Handler: ng.managedKeysEligible,
},
{
Path: waitingManagedKeys,
Method: http.MethodGet,
Handler: ng.managedKeysWaiting,
},
}
ng.endpoints = endpoints

Expand Down Expand Up @@ -338,6 +359,55 @@ func (ng *nodeGroup) connectedPeersRatings(c *gin.Context) {
)
}

// managedKeysCount returns the node's number of managed keys
func (ng *nodeGroup) managedKeysCount(c *gin.Context) {
count := ng.getFacade().GetManagedKeysCount()
c.JSON(
http.StatusOK,
shared.GenericAPIResponse{
Data: gin.H{"count": count},
Error: "",
Code: shared.ReturnCodeSuccess,
},
)
}

// managedKeysEligible returns the node's eligible managed keys
func (ng *nodeGroup) managedKeysEligible(c *gin.Context) {
keys, err := ng.getFacade().GetEligibleManagedKeys()
if err != nil {
shared.RespondWithInternalError(c, errors.ErrGetEligibleManagedKeys, err)
return
}

c.JSON(
http.StatusOK,
shared.GenericAPIResponse{
Data: gin.H{"eligibleKeys": keys},
Error: "",
Code: shared.ReturnCodeSuccess,
},
)
}

// managedKeysWaiting returns the node's waiting managed keys
func (ng *nodeGroup) managedKeysWaiting(c *gin.Context) {
keys, err := ng.getFacade().GetWaitingManagedKeys()
if err != nil {
shared.RespondWithInternalError(c, errors.ErrGetWaitingManagedKeys, err)
return
}

c.JSON(
http.StatusOK,
shared.GenericAPIResponse{
Data: gin.H{"waitingKeys": keys},
Error: "",
Code: shared.ReturnCodeSuccess,
},
)
}

func (ng *nodeGroup) getFacade() nodeFacadeHandler {
ng.mutFacade.RLock()
defer ng.mutFacade.RUnlock()
Expand Down
169 changes: 169 additions & 0 deletions api/groups/nodeGroup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,27 @@ type epochStartResponse struct {
generalResponse
}

type managedKeysCountResponse struct {
Data struct {
Count int `json:"count"`
} `json:"data"`
generalResponse
}

type managedEligibleKeysResponse struct {
Data struct {
Keys []string `json:"eligibleKeys"`
} `json:"data"`
generalResponse
}

type managedWaitingKeysResponse struct {
Data struct {
Keys []string `json:"waitingKeys"`
} `json:"data"`
generalResponse
}

func init() {
gin.SetMode(gin.TestMode)
}
Expand Down Expand Up @@ -651,6 +672,151 @@ func TestPrometheusMetrics_ShouldWork(t *testing.T) {
assert.True(t, keyAndValueFoundInResponse)
}

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

providedCount := 1000
facade := mock.FacadeStub{
GetManagedKeysCountCalled: func() int {
return providedCount
},
}

nodeGroup, err := groups.NewNodeGroup(&facade)
require.NoError(t, err)

ws := startWebServer(nodeGroup, "node", getNodeRoutesConfig())

req, _ := http.NewRequest("GET", "/node/managed-keys/count", nil)
resp := httptest.NewRecorder()
ws.ServeHTTP(resp, req)

response := &managedKeysCountResponse{}
loadResponse(resp.Body, response)

assert.Equal(t, http.StatusOK, resp.Code)
assert.Equal(t, "", response.Error)
assert.Equal(t, providedCount, response.Data.Count)
}

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

t.Run("facade error should error", func(t *testing.T) {
t.Parallel()

facade := mock.FacadeStub{
GetEligibleManagedKeysCalled: func() ([]string, error) {
return nil, expectedErr
},
}

nodeGroup, err := groups.NewNodeGroup(&facade)
require.NoError(t, err)

ws := startWebServer(nodeGroup, "node", getNodeRoutesConfig())

req, _ := http.NewRequest("GET", "/node/managed-keys/eligible", nil)
resp := httptest.NewRecorder()
ws.ServeHTTP(resp, req)

response := &shared.GenericAPIResponse{}
loadResponse(resp.Body, response)

assert.Equal(t, http.StatusInternalServerError, resp.Code)
assert.True(t, strings.Contains(response.Error, expectedErr.Error()))
})
t.Run("should work", func(t *testing.T) {
t.Parallel()

providedKeys := []string{
"key1",
"key2",
"key3",
}
facade := mock.FacadeStub{
GetEligibleManagedKeysCalled: func() ([]string, error) {
return providedKeys, nil
},
}

nodeGroup, err := groups.NewNodeGroup(&facade)
require.NoError(t, err)

ws := startWebServer(nodeGroup, "node", getNodeRoutesConfig())

req, _ := http.NewRequest("GET", "/node/managed-keys/eligible", nil)
resp := httptest.NewRecorder()
ws.ServeHTTP(resp, req)

response := &managedEligibleKeysResponse{}
loadResponse(resp.Body, response)

assert.Equal(t, http.StatusOK, resp.Code)
assert.Equal(t, "", response.Error)
assert.Equal(t, providedKeys, response.Data.Keys)
})
}

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

t.Run("facade error should error", func(t *testing.T) {
t.Parallel()

facade := mock.FacadeStub{
GetWaitingManagedKeysCalled: func() ([]string, error) {
return nil, expectedErr
},
}

nodeGroup, err := groups.NewNodeGroup(&facade)
require.NoError(t, err)

ws := startWebServer(nodeGroup, "node", getNodeRoutesConfig())

req, _ := http.NewRequest("GET", "/node/managed-keys/waiting", nil)
resp := httptest.NewRecorder()
ws.ServeHTTP(resp, req)

response := &shared.GenericAPIResponse{}
loadResponse(resp.Body, response)

assert.Equal(t, http.StatusInternalServerError, resp.Code)
assert.True(t, strings.Contains(response.Error, expectedErr.Error()))
})
t.Run("should work", func(t *testing.T) {
t.Parallel()

providedKeys := []string{
"key1",
"key2",
"key3",
}
facade := mock.FacadeStub{
GetWaitingManagedKeysCalled: func() ([]string, error) {
return providedKeys, nil
},
}

nodeGroup, err := groups.NewNodeGroup(&facade)
require.NoError(t, err)

ws := startWebServer(nodeGroup, "node", getNodeRoutesConfig())

req, _ := http.NewRequest("GET", "/node/managed-keys/waiting", nil)
resp := httptest.NewRecorder()
ws.ServeHTTP(resp, req)

response := &managedWaitingKeysResponse{}
loadResponse(resp.Body, response)

assert.Equal(t, http.StatusOK, resp.Code)
assert.Equal(t, "", response.Error)
assert.Equal(t, providedKeys, response.Data.Keys)
})
}

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

Expand Down Expand Up @@ -758,6 +924,9 @@ func getNodeRoutesConfig() config.ApiRoutesConfig {
{Name: "/epoch-start/:epoch", Open: true},
{Name: "/bootstrapstatus", Open: true},
{Name: "/connected-peers-ratings", Open: true},
{Name: "/managed-keys/count", Open: true},
{Name: "/managed-keys/eligible", Open: true},
{Name: "/managed-keys/waiting", Open: true},
},
},
},
Expand Down
27 changes: 27 additions & 0 deletions api/mock/facadeStub.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ type FacadeStub struct {
PprofEnabledCalled func() bool
DecodeAddressPubkeyCalled func(pk string) ([]byte, error)
IsDataTrieMigratedCalled func(address string, options api.AccountQueryOptions) (bool, error)
GetManagedKeysCountCalled func() int
GetEligibleManagedKeysCalled func() ([]string, error)
GetWaitingManagedKeysCalled func() ([]string, error)
}

// GetTokenSupply -
Expand Down Expand Up @@ -573,6 +576,30 @@ func (f *FacadeStub) IsSelfTrigger() bool {
return false
}

// GetManagedKeysCount -
func (f *FacadeStub) GetManagedKeysCount() int {
if f.GetManagedKeysCountCalled != nil {
return f.GetManagedKeysCountCalled()
}
return 0
}

// GetEligibleManagedKeys -
func (f *FacadeStub) GetEligibleManagedKeys() ([]string, error) {
if f.GetEligibleManagedKeysCalled != nil {
return f.GetEligibleManagedKeysCalled()
}
return make([]string, 0), nil
}

// GetWaitingManagedKeys -
func (f *FacadeStub) GetWaitingManagedKeys() ([]string, error) {
if f.GetWaitingManagedKeysCalled != nil {
return f.GetWaitingManagedKeysCalled()
}
return make([]string, 0), nil
}

// Close -
func (f *FacadeStub) Close() error {
return nil
Expand Down
3 changes: 3 additions & 0 deletions api/shared/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,5 +127,8 @@ type FacadeHandler interface {
GetLastPoolNonceForSender(sender string) (uint64, error)
GetTransactionsPoolNonceGapsForSender(sender string) (*common.TransactionsPoolNonceGapsForSenderApiResponse, error)
IsDataTrieMigrated(address string, options api.AccountQueryOptions) (bool, error)
GetManagedKeysCount() int
GetEligibleManagedKeys() ([]string, error)
GetWaitingManagedKeys() ([]string, error)
IsInterfaceNil() bool
}
11 changes: 10 additions & 1 deletion cmd/node/config/api.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,16 @@
{ Name = "/bootstrapstatus", Open = true },

# /node/connected-peers-ratings will return the peers ratings
{ Name = "/connected-peers-ratings", Open = true }
{ Name = "/connected-peers-ratings", Open = true },

# /node/managed-keys/count will return the number of keys managed by the node
{ Name = "/managed-keys/count", Open = true },

# /node/managed-keys/eligible will return the eligible keys managed by the node on the current epoch
{ Name = "/managed-keys/eligible", Open = true },

# /node/managed-keys/waiting will return the waiting keys managed by the node on the current epoch
{ Name = "/managed-keys/waiting", Open = true }
]

[APIPackages.address]
Expand Down
8 changes: 8 additions & 0 deletions common/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -426,3 +426,11 @@ type StateSyncNotifierSubscriber interface {
MissingDataTrieNodeFound(hash []byte)
IsInterfaceNil() bool
}

// ManagedPeersMonitor defines the operations of an entity that monitors the managed peers holder
type ManagedPeersMonitor interface {
GetManagedKeysCount() int
GetEligibleManagedKeys() ([][]byte, error)
GetWaitingManagedKeys() ([][]byte, error)
IsInterfaceNil() bool
}