Skip to content

Commit

Permalink
chore: add gno-exporter POC
Browse files Browse the repository at this point in the history
  • Loading branch information
albttx committed Oct 18, 2023
1 parent 89428c5 commit 120158f
Show file tree
Hide file tree
Showing 11 changed files with 605 additions and 0 deletions.
1 change: 1 addition & 0 deletions misc/gno-exporter/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
gno-exporter
54 changes: 54 additions & 0 deletions misc/gno-exporter/gno-collectors/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package gnoexporter

import (
"log"
"net/http"

rpcClient "github.com/gnolang/gno/tm2/pkg/bft/rpc/client"
"github.com/prometheus/client_golang/prometheus/promhttp"
)

type GnoCollector struct {
client rpcClient.Client

opts GnoCollectorOpts
}

type GnoCollectorOpts struct {
RPCURL string

Collectors []Collector
}

func NewGnoCollector(opts GnoCollectorOpts) *GnoCollector {
client := rpcClient.NewHTTP(opts.RPCURL, "")

opts.Collectors = append(opts.Collectors,
AccountCollector{client: client},
RealmCollector{client: client},
RDemoUsers{client: client},
)

return &GnoCollector{
client: client,
opts: opts,
}
}

func (c GnoCollector) GetClient() rpcClient.Client {
return c.client
}

func (c GnoCollector) AddCollectors(collectors ...Collector) {
c.opts.Collectors = append(c.opts.Collectors, collectors...)
}

func (c GnoCollector) Start(addr string) error {
for _, collector := range c.opts.Collectors {
log.Println("Setting collector: ", collector.Pattern())
http.HandleFunc(collector.Pattern(), collector.Collect())
}

http.Handle("/metrics", promhttp.Handler())
return http.ListenAndServe(addr, nil)
}
10 changes: 10 additions & 0 deletions misc/gno-exporter/gno-collectors/collector.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package gnoexporter

import (
"net/http"
)

type Collector interface {
Pattern() string
Collect() http.HandlerFunc
}
60 changes: 60 additions & 0 deletions misc/gno-exporter/gno-collectors/collector_account.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package gnoexporter

import (
"log"
"net/http"

rpcClient "github.com/gnolang/gno/tm2/pkg/bft/rpc/client"

_ "github.com/gnolang/gno/tm2/pkg/crypto/secp256k1"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)

// AccountCollector is complient with the Collector interface
type AccountCollector struct {
client rpcClient.Client
}

func (c AccountCollector) Pattern() string {
return "/metrics/account"
}

func (c AccountCollector) Collect() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
registry := prometheus.NewRegistry()
address := r.URL.Query().Get("address")

accountBalanceGauge := prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "gno_account_balance",
Help: "Gno account balance",
// ConstLabels: prometheus.Labels,
}, []string{"address", "denom"})
registry.MustRegister(accountBalanceGauge)

sequenceBalanceGauge := prometheus.NewCounter(
prometheus.CounterOpts{
Name: "gno_account_sequence",
Help: "Gno account sequence",
// ConstLabels: prometheus.Labels,
})
registry.MustRegister(sequenceBalanceGauge)

account, err := getAccount(c.client, address)
if err != nil {
log.Printf("failed to get account '%s', err: %v", address, err)
return
}

accountBalanceGauge.With(prometheus.Labels{
"address": address,
"denom": "ugnot",
}).Set(float64(account.GetCoins().AmountOf("ugnot")))

sequenceBalanceGauge.Add(float64(account.GetSequence()))

h := promhttp.HandlerFor(registry, promhttp.HandlerOpts{})
h.ServeHTTP(w, r)
}
}
55 changes: 55 additions & 0 deletions misc/gno-exporter/gno-collectors/collector_r-demo-users.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package gnoexporter

import (
"log"
"net/http"
"regexp"
"strconv"

rpcClient "github.com/gnolang/gno/tm2/pkg/bft/rpc/client"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)

// RDemoUsers is complient with the Collector interface
type RDemoUsers struct {
client rpcClient.Client
}

func (c RDemoUsers) Pattern() string {
return "/metrics/r/demo/users"
}

func (c RDemoUsers) Collect() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
registry := prometheus.NewRegistry()

realmSequenceBalanceCounter := prometheus.NewCounter(
prometheus.CounterOpts{
Name: "gno_r_demo_users",
Help: "Gno Realm account sequence",
// ConstLabels: prometheus.Labels,
})
registry.MustRegister(realmSequenceBalanceCounter)

res, err := c.client.ABCIQuery("vm/qeval", []byte("gno.land/r/demo/users\ncounter"))
if err != nil {
log.Printf("failed to Query r/demo/users.counter, err: %v", err)
return
}

re := regexp.MustCompile("[0-9]+")
counterStr := re.FindString(string(res.Response.Data))

counter, err := strconv.Atoi(counterStr)
if err != nil {
log.Printf("failed to strconv: %s, err: %v", res.Response.Data, err)
return
}

realmSequenceBalanceCounter.Add(float64(counter))

h := promhttp.HandlerFor(registry, promhttp.HandlerOpts{})
h.ServeHTTP(w, r)
}
}
62 changes: 62 additions & 0 deletions misc/gno-exporter/gno-collectors/collector_realm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package gnoexporter

import (
"log"
"net/http"

"github.com/gnolang/gno/gnovm/pkg/gnolang"
rpcClient "github.com/gnolang/gno/tm2/pkg/bft/rpc/client"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)

// RealmCollector is complient with the Collector interface
type RealmCollector struct {
client rpcClient.Client
}

func (c RealmCollector) Pattern() string {
return "/metrics/realm"
}

func (c RealmCollector) Collect() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
registry := prometheus.NewRegistry()
path := r.URL.Query().Get("path")

address := gnolang.DerivePkgAddr(path)

realmAccountBalanceGauge := prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "gno_realm_account_balance",
Help: "Gno realm account balance",
// ConstLabels: prometheus.Labels,
}, []string{"realm_path", "address", "denom"})
registry.MustRegister(realmAccountBalanceGauge)

realmSequenceBalanceGauge := prometheus.NewCounter(
prometheus.CounterOpts{
Name: "gno_realm_account_sequence",
Help: "Gno Realm account sequence",
// ConstLabels: prometheus.Labels,
})
registry.MustRegister(realmSequenceBalanceGauge)

account, err := getAccount(c.client, address.String())
if err != nil {
log.Printf("failed to get account '%s', err: %v", address, err)
return
}

realmAccountBalanceGauge.With(prometheus.Labels{
"realm_path": path,
"address": address.String(),
"denom": "ugnot",
}).Set(float64(account.GetCoins().AmountOf("ugnot")))

realmSequenceBalanceGauge.Add(float64(account.GetSequence()))

h := promhttp.HandlerFor(registry, promhttp.HandlerOpts{})
h.ServeHTTP(w, r)
}
}
32 changes: 32 additions & 0 deletions misc/gno-exporter/gno-collectors/get_account.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package gnoexporter

import (
"fmt"

"github.com/gnolang/gno/tm2/pkg/amino"
rpcClient "github.com/gnolang/gno/tm2/pkg/bft/rpc/client"
"github.com/gnolang/gno/tm2/pkg/crypto"
"github.com/gnolang/gno/tm2/pkg/std"
)

func getAccount(client rpcClient.Client, address string) (std.Account, error) {
addr, err := crypto.AddressFromBech32(address)
if err != nil {
return nil, fmt.Errorf("failed to parse address: %s, %w", address, err)
}

path := fmt.Sprintf("auth/accounts/%s", addr.String())

queryResponse, err := client.ABCIQuery(path, []byte{})
if err != nil {
return nil, fmt.Errorf("unable to execute ABCI query, %w", err)
}

var queryData struct{ BaseAccount std.BaseAccount }

if err := amino.UnmarshalJSON(queryResponse.Response.Data, &queryData); err != nil {
return nil, err
}

return &queryData.BaseAccount, nil
}
55 changes: 55 additions & 0 deletions misc/gno-exporter/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
module github.com/gnolang/gno/misc/gno-exporter

go 1.19

replace github.com/gnolang/gno => ../../

require (
github.com/gnolang/gno v0.0.0-00010101000000-000000000000
github.com/prometheus/client_golang v1.17.0
)

require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c // indirect
github.com/btcsuite/btcd/btcutil v1.0.0 // indirect
github.com/cespare/xxhash v1.1.0 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cockroachdb/apd v1.1.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgraph-io/badger/v3 v3.2103.4 // indirect
github.com/dgraph-io/ristretto v0.1.1 // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/gnolang/goleveldb v0.0.9 // indirect
github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/flatbuffers v1.12.1 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/jmhodges/levigo v1.0.0 // indirect
github.com/klauspost/compress v1.12.3 // indirect
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
github.com/linxGnu/grocksdb v1.8.4 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect
github.com/prometheus/common v0.44.0 // indirect
github.com/prometheus/procfs v0.11.1 // indirect
github.com/rs/cors v1.10.1 // indirect
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect
go.etcd.io/bbolt v1.3.7 // indirect
go.opencensus.io v0.22.5 // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/crypto v0.13.0 // indirect
golang.org/x/mod v0.13.0 // indirect
golang.org/x/net v0.15.0 // indirect
golang.org/x/sys v0.12.0 // indirect
golang.org/x/tools v0.13.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
)
Loading

0 comments on commit 120158f

Please sign in to comment.