-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #22 from samcm/feat/peers
feat(consensus): Add Peers metrics
- Loading branch information
Showing
10 changed files
with
272 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
package api | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"io" | ||
"net/http" | ||
"time" | ||
|
||
"github.com/samcm/ethereum-metrics-exporter/pkg/exporter/consensus/api/types" | ||
"github.com/sirupsen/logrus" | ||
) | ||
|
||
// ConsensusClient is an interface for executing RPC calls to the Ethereum node. | ||
type ConsensusClient interface { | ||
NodePeer(ctx context.Context, peerID string) (types.Peer, error) | ||
NodePeers(ctx context.Context) (types.Peers, error) | ||
NodePeerCount(ctx context.Context) (types.PeerCount, error) | ||
} | ||
|
||
type consensusClient struct { | ||
url string | ||
log logrus.FieldLogger | ||
client http.Client | ||
} | ||
|
||
// NewConsensusClient creates a new ConsensusClient. | ||
func NewConsensusClient(ctx context.Context, log logrus.FieldLogger, url string) ConsensusClient { | ||
client := http.Client{ | ||
Timeout: time.Second * 10, | ||
} | ||
|
||
return &consensusClient{ | ||
url: url, | ||
log: log, | ||
client: client, | ||
} | ||
} | ||
|
||
type apiResponse struct { | ||
Data json.RawMessage `json:"data"` | ||
} | ||
|
||
//nolint:unparam // ctx will probably be used in the future | ||
func (c *consensusClient) post(ctx context.Context, path string, body map[string]interface{}) (json.RawMessage, error) { | ||
jsonData, err := json.Marshal(body) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
rsp, err := c.client.Post(c.url, "application/json", bytes.NewBuffer(jsonData)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
defer rsp.Body.Close() | ||
|
||
if rsp.StatusCode != http.StatusOK { | ||
return nil, fmt.Errorf("status code: %d", rsp.StatusCode) | ||
} | ||
|
||
data, err := io.ReadAll(rsp.Body) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
resp := new(apiResponse) | ||
if err := json.Unmarshal(data, resp); err != nil { | ||
return nil, err | ||
} | ||
|
||
return resp.Data, nil | ||
} | ||
|
||
//nolint:unparam // ctx will probably be used in the future | ||
func (c *consensusClient) get(ctx context.Context, path string) (json.RawMessage, error) { | ||
rsp, err := c.client.Get(c.url + path) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
defer rsp.Body.Close() | ||
|
||
if rsp.StatusCode != http.StatusOK { | ||
return nil, fmt.Errorf("status code: %d", rsp.StatusCode) | ||
} | ||
|
||
data, err := io.ReadAll(rsp.Body) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
resp := new(apiResponse) | ||
if err := json.Unmarshal(data, resp); err != nil { | ||
return nil, err | ||
} | ||
|
||
return resp.Data, nil | ||
} | ||
|
||
func (c *consensusClient) NodePeers(ctx context.Context) (types.Peers, error) { | ||
data, err := c.get(ctx, "/eth/v1/node/peers") | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
rsp := types.Peers{} | ||
if err := json.Unmarshal(data, &rsp); err != nil { | ||
return nil, err | ||
} | ||
|
||
return rsp, nil | ||
} | ||
|
||
func (c *consensusClient) NodePeer(ctx context.Context, peerID string) (types.Peer, error) { | ||
data, err := c.get(ctx, fmt.Sprintf("/eth/v1/node/peers/%s", peerID)) | ||
if err != nil { | ||
return types.Peer{}, err | ||
} | ||
|
||
rsp := types.Peer{} | ||
if err := json.Unmarshal(data, &rsp); err != nil { | ||
return types.Peer{}, err | ||
} | ||
|
||
return rsp, nil | ||
} | ||
|
||
func (c *consensusClient) NodePeerCount(ctx context.Context) (types.PeerCount, error) { | ||
data, err := c.get(ctx, "/eth/v1/node/peer_count") | ||
if err != nil { | ||
return types.PeerCount{}, err | ||
} | ||
|
||
rsp := types.PeerCount{} | ||
if err := json.Unmarshal(data, &rsp); err != nil { | ||
return types.PeerCount{}, err | ||
} | ||
|
||
return rsp, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package types | ||
|
||
var PeerStates = []string{ | ||
"disconnected", | ||
"connected", | ||
"connecting", | ||
"disconnecting", | ||
} | ||
|
||
var PeerDirections = []string{ | ||
"inbound", | ||
"outbound", | ||
} | ||
|
||
type Peer struct { | ||
PeerID string `json:"peer_id"` | ||
ENR string `json:"enr"` | ||
LastSeenP2PAddress string `json:"last_seen_p2p_address"` | ||
State string `json:"state"` | ||
Direction string `json:"direction"` | ||
} | ||
|
||
type Peers []Peer | ||
|
||
type PeerCount struct { | ||
Disconnected string `json:"disconnected"` | ||
Connected string `json:"connected"` | ||
Connecting string `json:"connecting"` | ||
Disconnecting string `json:"disconnecting"` | ||
} | ||
|
||
func (p *Peers) ByState(state string) Peers { | ||
var peers []Peer | ||
|
||
for _, peer := range *p { | ||
if peer.State == state { | ||
peers = append(peers, peer) | ||
} | ||
} | ||
|
||
return peers | ||
} | ||
|
||
func (p *Peers) ByDirection(direction string) Peers { | ||
var peers []Peer | ||
|
||
for _, peer := range *p { | ||
if peer.Direction == direction { | ||
peers = append(peers, peer) | ||
} | ||
} | ||
|
||
return peers | ||
} | ||
|
||
func (p *Peers) ByStateAndDirection(state, direction string) Peers { | ||
var peers []Peer | ||
|
||
for _, peer := range *p { | ||
if peer.State == state && peer.Direction == direction { | ||
peers = append(peers, peer) | ||
} | ||
} | ||
|
||
return peers | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.