diff --git a/.github/workflows/go-test.yaml b/.github/workflows/go-test.yaml index 67e0e0f..79f8672 100644 --- a/.github/workflows/go-test.yaml +++ b/.github/workflows/go-test.yaml @@ -32,7 +32,7 @@ jobs: run: go test -v -coverprofile=coverage.out ./... - name: Upload coverage report - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: coverage-report - path: coverage.out \ No newline at end of file + path: coverage.out diff --git a/CHANGELOG.md b/CHANGELOG.md index d36d33b..084ddf1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,23 +12,26 @@ and more configurability. Below is a list of newly added metrics (see the [README](README.md) for metric descriptions): -* `solana_account_balance` ([@johnstonematt](https://github.com/johnstonematt)) -* `solana_node_is_healthy` ([@GranderStark](https://github.com/GranderStark)) -* `solana_nude_num_slots_behind` ([@GranderStark](https://github.com/GranderStark)) -* `solana_node_minimum_ledger_slot` ([@GranderStark](https://github.com/GranderStark)) -* `solana_node_first_available_block` ([@GranderStark](https://github.com/GranderStark)) -* `solana_cluster_slots_by_epoch_total` ([@johnstonematt](https://github.com/johnstonematt)) -* `solana_validator_fee_rewards` ([@johnstonematt](https://github.com/johnstonematt)) -* `solana_validator_block_size` ([@johnstonematt](https://github.com/johnstonematt)) -* `solana_node_block_height` ([@GranderStark](https://github.com/GranderStark)) -* `solana_cluster_active_stake` ([@johnstonematt](https://github.com/johnstonematt)) -* `solana_cluster_last_vote` ([@johnstonematt](https://github.com/johnstonematt)) -* `solana_cluster_root_slot` ([@johnstonematt](https://github.com/johnstonematt)) -* `solana_cluster_validator_count` ([@johnstonematt](https://github.com/johnstonematt)) +* `solana_account_balance` (**[@johnstonematt](https://github.com/johnstonematt)**) +* `solana_node_is_healthy` (**[@GranderStark](https://github.com/GranderStark)**) +* `solana_node_num_slots_behind` (**[@GranderStark](https://github.com/GranderStark)**) +* `solana_node_minimum_ledger_slot` (**[@GranderStark](https://github.com/GranderStark)**) +* `solana_node_first_available_block` (**[@GranderStark](https://github.com/GranderStark)**) +* `solana_cluster_slots_by_epoch_total` (**[@johnstonematt](https://github.com/johnstonematt)**) +* `solana_validator_fee_rewards` (**[@johnstonematt](https://github.com/johnstonematt)**) +* `solana_validator_block_size` (**[@johnstonematt](https://github.com/johnstonematt)**) +* `solana_node_block_height` (**[@GranderStark](https://github.com/GranderStark)**) +* `solana_cluster_active_stake` (**[@johnstonematt](https://github.com/johnstonematt)**) +* `solana_cluster_last_vote` (**[@johnstonematt](https://github.com/johnstonematt)**) +* `solana_cluster_root_slot` (**[@johnstonematt](https://github.com/johnstonematt)**) +* `solana_cluster_validator_count` (**[@johnstonematt](https://github.com/johnstonematt)**) +* `solana_node_identity` (**[@impactdni2](https://github.com/impactdni2)**) +* `solana_node_is_active` (**[@andreclaro](https://github.com/andreclaro)**) +* `solana_foundation_min_required_version` (**[@qedgardo](https://github.com/qedgardo)**) #### Renamed Metrics -The table below contains all metrics renamed in `v3.0.0` ([@johnstonematt](https://github.com/johnstonematt)): +The table below contains all metrics renamed in `v3.0.0` (**[@johnstonematt](https://github.com/johnstonematt)**): | Old Name | New Name | |---------------------------------------|------------------------------------------------| @@ -50,14 +53,14 @@ Metrics were renamed to: #### Label Updates -The following labels were renamed ([@johnstonematt](https://github.com/johnstonematt)): +The following labels were renamed (**[@johnstonematt](https://github.com/johnstonematt)**): * `pubkey` was renamed to `votekey`, to clearly identity that it refers to the address of a validators vote account. ### Config Updates #### New Config Parameters Below is a list of newly added config parameters (see the [README](README.md) -for parameter descriptions) ([@johnstonematt](https://github.com/johnstonematt)): +for parameter descriptions) (**[@johnstonematt](https://github.com/johnstonematt)**): * `-balance-address` * `-nodekey` @@ -67,10 +70,12 @@ for parameter descriptions) ([@johnstonematt](https://github.com/john * `-light-mode` * `-http-timeout` * `-comprehensive-vote-account-tracking` + * `-active-identity` + * `epoch-cleanup-time` #### Renamed Config Parameters -The table below contains all config parameters renamed in `v3.0.0` ([@johnstonematt](https://github.com/johnstonematt)): +The table below contains all config parameters renamed in `v3.0.0` (**[@johnstonematt](https://github.com/johnstonematt)**): | Old Name | New Name | |-------------------------------------|-------------------| @@ -79,21 +84,25 @@ The table below contains all config parameters renamed in `v3.0.0` ([ #### Removed Config Parameters -The following metrics were removed ([@johnstonematt](https://github.com/johnstonematt)): +The following metrics were removed (**[@johnstonematt](https://github.com/johnstonematt)**): * `votepubkey`. Configure validator tracking using the `-nodekey` parameter. ### General Updates * The project was renamed from `solana_exporter` to `solana-exporter`, to conform with -[Go naming conventions](https://github.com/unknwon/go-code-convention/blob/main/en-US.md) ([@johnstonematt](https://github.com/johnstonematt)). -* Testing was significantly improved ([@johnstonematt](https://github.com/johnstonematt)). +[Go naming conventions](https://github.com/unknwon/go-code-convention/blob/main/en-US.md) (**[@johnstonematt](https://github.com/johnstonematt)**). +* Testing was significantly improved (**[@johnstonematt](https://github.com/johnstonematt)**). * [klog](https://github.com/kubernetes/klog) logging was removed and replaced with [zap](https://github.com/uber-go/zap) - ([@johnstonematt](https://github.com/johnstonematt)) -* Easy usage ([@johnstonematt](https://github.com/johnstonematt)): + (**[@johnstonematt](https://github.com/johnstonematt)**) +* Easy usage (**[@johnstonematt](https://github.com/johnstonematt)**): * The example dashboard was updated. * An example prometheus config was added, as well as recording rules for tracking skip rate. ## New Contributors -* [@GranderStark](https://github.com/GranderStark) made their first contribution. +* **[@GranderStark](https://github.com/GranderStark)** made their first contribution in **[#33](https://github.com/asymmetric-research/solana-exporter/pull/33)**. +* **[@dylanschultzie](https://github.com/dylanschultzie)** made their first contribution in **[#49](https://github.com/asymmetric-research/solana-exporter/pull/49)**. +* **[@impactdni2](https://github.com/impactdni2)** made their first contribution in **[#83](https://github.com/asymmetric-research/solana-exporter/pull/83)**. +* **[@andreclaro](https://github.com/andreclaro)** made their first contribution in **[#84](https://github.com/asymmetric-research/solana-exporter/pull/84)**. +* **[@qedgardo](https://github.com/quedgardo)** made their first contribution in **[#85](https://github.com/asymmetric-research/solana-exporter/pull/85)**. diff --git a/README.md b/README.md index 90d4042..acf0c8c 100644 --- a/README.md +++ b/README.md @@ -15,10 +15,61 @@ solana-exporter \ -balance-address -balance-address \ -comprehensive-slot-tracking \ -monitor-block-sizes + -active-identity ``` ![Solana Exporter Dashboard Sample](assets/solana-dashboard-screenshot.png) +### Features +#### Balance Tracking + +Using the `-balance-address
` configuration parameter, the exporter can be used to monitor any account's +SOL balance. This parameter can be set multiple times to track multiple accounts. Additionally, the balance of all +configured `-nodekey`'s is automatically tracked. + +#### Block Sizes + +If the `-monitor-block-sizes` flag is set, then the exporter will export the number of transactions (both vote-only and +non-vote transactions) in blocks produced by the monitored validators. This is a critical validator performance metric. + +Cluster average block size can be inferred by dividing total network transactions by total block height. + +#### Income Reporting + +The exporter exports metrics regarding total priority fee revenue and inflation reward revenue earned by the +monitored validators. + +#### Skip Rate + +The exporter does not directly export skip rate, as this needs to be defined as an average over a desired timeframe. +However, the exporter does track the monitored validators leader slots and whether they are `valid` or `skipped`. + +The example prometheus setup contains [recording rules](prometheus/solana-rules.yml) for measuring average skip rate +for both individual validators and a cluster-level over hourly, daily and epoch intervals. + +#### Active/Passive Monitoring + +The `solana_node_is_active` metric simply reports whether the node (on which the exporter is running) has the same +identity-keypair as that configured with the `-active-identity` flag. The `-active-identity` flag should be used to +specify the primary identity when using a +[non-delinquent backup validator](https://pumpkins-pool.gitbook.io/pumpkins-pool). + +#### Light Mode + +Certain metrics, such as validator leader slots, income, block size and active stake, are visible on-chain through any +trusted node. However, other metrics such as node health and block height can only be viewed from an exporter running +on the node in question. Thus, on a node in which fine margins of performance are of critical interest, the exporter +can be set to `-light-mode`. In light mode, it will only export metrics that cannot be viewed from other nodes. + +This is particularly useful in setups that contain an important validator and utility RPC node - the exporter can be +run in light mode on the validator and in full capacity on the RPC node (configured to monitor the validator through +use of the `-nodekey` parameter). + +#### General Performance and Health + +In addition to the above features, the exporter provides key metrics for monitoring Solana node health and performance. +See [Metrics](#metrics) below for more details. + ## Installation ### Build @@ -49,6 +100,7 @@ The exporter is configured via the following command line arguments: | `-rpc-url` | Solana RPC URL (including protocol and path), e.g., `"http://localhost:8899"` or `"https://api.mainnet-beta.solana.com"` | `"http://localhost:8899"` | | `-slot-pace` | This is the time (in seconds) between slot-watching metric collections | `1` | | `-active-identity` | Validator identity public key used to determine if the node is considered active in the `solana_node_is_active` metric. | N/A | +| `-epoch-cleanup-time` | The time to wait before cleaning old epoch metrics from the prometheus endpoint. | | ### Notes on Configuration @@ -96,11 +148,6 @@ The tables below describes all the metrics collected by the `solana-exporter`: | `solana_node_is_active` | Whether the node is active and participating in consensus. | `identity` | | `solana_foundation_min_required_version` | Minimum required Solana version for the [solana foundation delegation program](https://solana.org/delegation-program) | `version`, `cluster` | -#### Light Mode - -In `-light-mode`, the exporter will only track metrics that uniquely to the node being queried. These metric names -all begin with `solana_node_*`. - #### Vote Account Metrics The following metrics are all received from the `getVoteAccounts` [RPC endpoint](https://solana.com/docs/rpc/http/getvoteaccounts): diff --git a/pkg/rpc/client.go b/pkg/rpc/client.go index b8d5355..53c4ef7 100644 --- a/pkg/rpc/client.go +++ b/pkg/rpc/client.go @@ -45,13 +45,12 @@ const ( // CommitmentProcessed level represents a transaction that has been received by the network and included in a block. CommitmentProcessed Commitment = "processed" - // Genesis hashes for different Solana clusters DevnetGenesisHash = "EtWTRABZaYq6iMfeYKouRu166VU2xqa1wcaWoxPkrZBG" TestnetGenesisHash = "4uhcVJyU9pJkvQyS88uRDiswHXSCkY3zQawwpjk2NsNY" MainnetGenesisHash = "5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d" ) -// getClusterFromGenesisHash returns the cluster name based on the genesis hash +// GetClusterFromGenesisHash returns the cluster name based on the genesis hash func GetClusterFromGenesisHash(hash string) (string, error) { switch hash { case DevnetGenesisHash: @@ -133,7 +132,6 @@ func (c *Client) GetEpochInfo(ctx context.Context, commitment Commitment) (*Epoc func (c *Client) GetVoteAccounts(ctx context.Context, commitment Commitment) (*VoteAccounts, error) { // format params: config := map[string]string{"commitment": string(commitment)} - var resp Response[VoteAccounts] if err := getResponse(ctx, c, "getVoteAccounts", []any{config}, &resp); err != nil { return nil, err @@ -186,7 +184,6 @@ func (c *Client) GetBlockProduction( "commitment": string(commitment), "range": map[string]int64{"firstSlot": firstSlot, "lastSlot": lastSlot}, } - // make request: var resp Response[contextualResult[BlockProduction]] if err := getResponse(ctx, c, "getBlockProduction", []any{config}, &resp); err != nil { @@ -213,7 +210,6 @@ func (c *Client) GetInflationReward( ) ([]InflationReward, error) { // format params: config := map[string]any{"commitment": string(commitment), "epoch": epoch} - var resp Response[[]InflationReward] if err := getResponse(ctx, c, "getInflationReward", []any{addresses, config}, &resp); err != nil { return nil, err