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

first implementation for economic metrics exporter sidecar #83

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions cmd/metrics_exporter/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Metrics Exporter Sidecar
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably wrap this in a Docker image, yeah?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep. moved PR to other repo and added docker stuff there. see https://github.com/Layr-Labs/eigenlayer-middleware-offchain/pull/2


This binary is meant to be run as a sidecar, to periodically query the contracts and export the economic metrics on a prometheus endpoint.

## Usage

```bash
go run . --avs-name my-avs --quorum-names-dict '{"0":"eth","1":"mycoin"}' --operator-addr 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 --registry-coordinator-addr 0x9E545E3C0baAB3E08CdfD552C960A1050f373042 --metrics-listening-addr localhost:9095
```
147 changes: 147 additions & 0 deletions cmd/metrics_exporter/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package main

import (
"encoding/json"
"fmt"
"net/http"
"os"

"github.com/ethereum/go-ethereum/common"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/urfave/cli/v2"

"github.com/Layr-Labs/eigensdk-go/chainio/constructor"
"github.com/Layr-Labs/eigensdk-go/logging"
"github.com/Layr-Labs/eigensdk-go/metrics/collectors/economic"
)

var (
AvsNameFlag = &cli.StringFlag{
Name: "avs-name",
Usage: "AVS name",
Required: true,
}
QuorumNamesDictFlag = &cli.StringFlag{
Name: "quorum-names-dict",
Usage: "quorum names dict (eg: '{0:eth,1:mycoin}')",
Required: true,
}
OperatorAddrFlag = &cli.StringFlag{
Name: "operator-addr",
Usage: "operator address",
Required: true,
}
RegistryCoordinatorAddrFlag = &cli.StringFlag{
Name: "registry-coordinator-addr",
Usage: "BLSRegistryCoordinatorWithIndices contract address",
Required: true,
}
MetricsListeningAddrFlag = &cli.StringFlag{
Name: "metrics-listening-addr",
Usage: "prometheus metrics listening address (eg: localhost:9095)",
Required: true,
}
RpcUrlFlag = &cli.StringFlag{
Name: "rpc-url",
Usage: "rpc url",
Value: "http://localhost:8545",
DefaultText: "http://localhost:8545",
}
LogLevelFlag = &cli.StringFlag{
Name: "log-level",
Usage: "logging level (production or development)",
Value: "production",
DefaultText: "production",
}
)

func main() {
run(os.Args)
}

// We structure run in this way to make it testable.
// see https://github.com/urfave/cli/issues/731
func run(args []string) {
app := cli.NewApp()
app.Name = "metrics-exporter"
app.Usage = "Ran as a AVS node sidecar to export metrics that are fetched from onchain contracts."
app.Description = "Currently only exports economic metrics."
app.Action = startCollector
app.Flags = []cli.Flag{
AvsNameFlag,
QuorumNamesDictFlag,
OperatorAddrFlag,
RegistryCoordinatorAddrFlag,
MetricsListeningAddrFlag,
RpcUrlFlag,
LogLevelFlag,
}

if err := app.Run(args); err != nil {
fmt.Println("Error: ", err)
os.Exit(1)
}

}

func startCollector(c *cli.Context) error {
logLevelStr := c.String(LogLevelFlag.Name)
var logLevel logging.LogLevel
if logLevelStr == "production" {
logLevel = logging.Production
} else if logLevelStr == "development" {
logLevel = logging.Development
} else {
return fmt.Errorf("invalid log level: %s", logLevelStr)
}
logger, err := logging.NewZapLogger(logLevel)
if err != nil {
return err
}

// TODO: we hardcode a bunch of things for now, waiting for chainio refactor PR to be merged
// https://github.com/Layr-Labs/eigensdk-go/pull/73
ethHttpUrl := c.String(RpcUrlFlag.Name)
// we don't even need this but are forced to pass one because constructor builds the websocket clients
ethWsUrl := "ws" + ethHttpUrl[4:]
constructorConfig := constructor.Config{
// we don't need writers for this exporter, but still need to pass this fake privatekey..
NimaVaziri marked this conversation as resolved.
Show resolved Hide resolved
EcdsaPrivateKeyString: "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80",
EthHttpUrl: ethHttpUrl,
EthWsUrl: ethWsUrl,
BlsRegistryCoordinatorAddr: c.String(RegistryCoordinatorAddrFlag.Name),
BlsOperatorStateRetrieverAddr: "", // not used by this exporter
AvsName: c.String(AvsNameFlag.Name),
PromMetricsIpPortAddress: c.String(MetricsListeningAddrFlag.Name),
}
clients, err := constructor.BuildClients(constructorConfig, logger)
if err != nil {
return err
}

operatorAddr := common.HexToAddress(c.String(OperatorAddrFlag.Name))
var quorumNamesDict map[uint8]string
if err := json.Unmarshal([]byte(c.String(QuorumNamesDictFlag.Name)), &quorumNamesDict); err != nil {
return err
}
economicCollector := economic.NewCollector(
clients.ElChainReader,
clients.AvsRegistryChainReader,
c.String(AvsNameFlag.Name),
logger,
operatorAddr,
quorumNamesDict,
)
reg := prometheus.NewRegistry()
reg.MustRegister(economicCollector)

metricsListeningAddr := c.String(MetricsListeningAddrFlag.Name)
logger.Infof("Starting metrics server at port %v", metricsListeningAddr)
http.Handle("/metrics", promhttp.HandlerFor(
reg,
promhttp.HandlerOpts{},
NimaVaziri marked this conversation as resolved.
Show resolved Hide resolved
))
err = http.ListenAndServe(metricsListeningAddr, nil)
NimaVaziri marked this conversation as resolved.
Show resolved Hide resolved
return err
}
Loading