Skip to content

Commit

Permalink
Merge pull request asymmetric-research#45 from asymmetric-research/mo…
Browse files Browse the repository at this point in the history
…re-config

More config updates
  • Loading branch information
johnstonematt authored Oct 17, 2024
2 parents db4d606 + 0985203 commit 39cfc3a
Show file tree
Hide file tree
Showing 5 changed files with 254 additions and 205 deletions.
98 changes: 98 additions & 0 deletions cmd/solana_exporter/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package main

import (
"flag"
"fmt"
"time"
)

type (
arrayFlags []string

ExporterConfig struct {
HttpTimeout time.Duration
RpcUrl string
ListenAddress string
NodeKeys []string
BalanceAddresses []string
ComprehensiveSlotTracking bool
}
)

func (i *arrayFlags) String() string {
return fmt.Sprint(*i)
}

func (i *arrayFlags) Set(value string) error {
*i = append(*i, value)
return nil
}

func NewExporterConfig(
httpTimeout int,
rpcUrl string,
listenAddress string,
nodeKeys []string,
balanceAddresses []string,
comprehensiveSlotTracking bool,
) *ExporterConfig {
return &ExporterConfig{
HttpTimeout: time.Duration(httpTimeout) * time.Second,
RpcUrl: rpcUrl,
ListenAddress: listenAddress,
NodeKeys: nodeKeys,
BalanceAddresses: balanceAddresses,
ComprehensiveSlotTracking: comprehensiveSlotTracking,
}
}

func NewExporterConfigFromCLI() *ExporterConfig {
var (
httpTimeout int
rpcUrl string
listenAddress string
nodekeys arrayFlags
balanceAddresses arrayFlags
comprehensiveSlotTracking bool
)
flag.IntVar(
&httpTimeout,
"http-timeout",
60,
"HTTP timeout to use, in seconds.",
)
flag.StringVar(
&rpcUrl,
"rpc-url",
"http://localhost:8899",
"Solana RPC URL (including protocol and path), "+
"e.g., 'http://localhost:8899' or 'https://api.mainnet-beta.solana.com'",
)
flag.StringVar(
&listenAddress,
"listen-address",
":8080",
"Listen address",
)
flag.Var(
&nodekeys,
"nodekey",
"Solana nodekey (identity account) representing validator to monitor - can set multiple times.",
)
flag.Var(
&balanceAddresses,
"balance-address",
"Address to monitor SOL balances for, in addition to the identity and vote accounts of the "+
"provided nodekeys - can be set multiple times.",
)
flag.BoolVar(
&comprehensiveSlotTracking,
"comprehensive-slot-tracking",
false,
"Set this flag to track solana_leader_slots_by_epoch for ALL validators. "+
"Warning: this will lead to potentially thousands of new Prometheus metrics being created every epoch.",
)
flag.Parse()

return NewExporterConfig(httpTimeout, rpcUrl, listenAddress, nodekeys, balanceAddresses, comprehensiveSlotTracking)
}
78 changes: 12 additions & 66 deletions cmd/solana_exporter/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@ package main

import (
"context"
"flag"
"github.com/asymmetric-research/solana_exporter/pkg/rpc"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"net/http"
"strings"
"time"

"k8s.io/klog/v2"
Expand All @@ -29,45 +27,6 @@ const (
StateDelinquent = "delinquent"
)

var (
httpTimeout = 60 * time.Second
// general config:
rpcUrl = flag.String(
"rpc-url",
"http://localhost:8899",
"Solana RPC URL (including protocol and path), "+
"e.g., 'http://localhost:8899' or 'https://api.mainnet-beta.solana.com'",
)
listenAddress = flag.String(
"listen-address",
":8080",
"Listen address",
)
httpTimeoutSecs = flag.Int(
"http-timeout",
60,
"HTTP timeout to use, in seconds.",
)
// parameters to specify what we're tracking:
nodekeys = flag.String(
"nodekeys",
"",
"Comma-separated list of nodekeys (identity accounts) representing validators to monitor.",
)
comprehensiveSlotTracking = flag.Bool(
"comprehensive-slot-tracking",
false,
"Set this flag to track solana_leader_slots_by_epoch for ALL validators. "+
"Warning: this will lead to potentially thousands of new Prometheus metrics being created every epoch.",
)
balanceAddresses = flag.String(
"balance-addresses",
"",
"Comma-separated list of addresses to monitor SOL balances for, "+
"in addition to the identity and vote accounts of the provided nodekeys.",
)
)

func init() {
klog.InitFlags(nil)
}
Expand Down Expand Up @@ -230,7 +189,7 @@ func (c *SolanaCollector) collectBalances(ctx context.Context, ch chan<- prometh
}

func (c *SolanaCollector) Collect(ch chan<- prometheus.Metric) {
ctx, cancel := context.WithTimeout(context.Background(), httpTimeout)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

c.collectVoteAccounts(ctx, ch)
Expand All @@ -240,43 +199,30 @@ func (c *SolanaCollector) Collect(ch chan<- prometheus.Metric) {

func main() {
ctx := context.Background()
flag.Parse()

if *comprehensiveSlotTracking {
config := NewExporterConfigFromCLI()
if config.ComprehensiveSlotTracking {
klog.Warning(
"Comprehensive slot tracking will lead to potentially thousands of new " +
"Prometheus metrics being created every epoch.",
)
}

httpTimeout = time.Duration(*httpTimeoutSecs) * time.Second

var (
balAddresses []string
validatorNodekeys []string
)
if *balanceAddresses != "" {
balAddresses = strings.Split(*balanceAddresses, ",")
}
if *nodekeys != "" {
validatorNodekeys = strings.Split(*nodekeys, ",")
klog.Infof("Monitoring the following validators: %v", validatorNodekeys)
client := rpc.NewRPCClient(config.RpcUrl, config.HttpTimeout)
votekeys, err := GetAssociatedVoteAccounts(ctx, client, rpc.CommitmentFinalized, config.NodeKeys)
if err != nil {
klog.Fatalf("Failed to get associated vote accounts for %v: %v", config.NodeKeys, err)
}

client := rpc.NewRPCClient(*rpcUrl)
ctx_, cancel := context.WithTimeout(ctx, httpTimeout)
collector := NewSolanaCollector(client, slotPacerSchedule, config.BalanceAddresses, config.NodeKeys, votekeys)
slotWatcher := NewSlotWatcher(client, config.NodeKeys, votekeys, config.ComprehensiveSlotTracking)
ctx, cancel := context.WithCancel(ctx)
defer cancel()
votekeys, err := GetAssociatedVoteAccounts(ctx_, client, rpc.CommitmentFinalized, validatorNodekeys)
if err != nil {
klog.Fatalf("Failed to get associated vote accounts for %v: %v", nodekeys, err)
}
collector := NewSolanaCollector(client, slotPacerSchedule, balAddresses, validatorNodekeys, votekeys)
slotWatcher := NewSlotWatcher(client, validatorNodekeys, votekeys, *comprehensiveSlotTracking)
go slotWatcher.WatchSlots(ctx, collector.slotPace)

prometheus.MustRegister(collector)
http.Handle("/metrics", promhttp.Handler())

klog.Infof("listening on %s", *listenAddress)
klog.Fatal(http.ListenAndServe(*listenAddress, nil))
klog.Infof("listening on %s", config.ListenAddress)
klog.Fatal(http.ListenAndServe(config.ListenAddress, nil))
}
Loading

0 comments on commit 39cfc3a

Please sign in to comment.