|
|
|
@ -1,9 +1,11 @@
|
|
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"flag"
|
|
|
|
|
"fmt"
|
|
|
|
|
"log"
|
|
|
|
|
"net/http"
|
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
|
|
"github.com/helium-blockchain-exporter/heliumapi"
|
|
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
|
|
@ -18,6 +20,7 @@ type metricInfo struct {
|
|
|
|
|
|
|
|
|
|
// Exporter collect metrics from the helium blockchain api and exports them as prometheus metrics.
|
|
|
|
|
type Exporter struct {
|
|
|
|
|
Accounts []string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
@ -25,6 +28,10 @@ const (
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var (
|
|
|
|
|
// lables
|
|
|
|
|
commonAccountLabels = []string{"account"}
|
|
|
|
|
commonHotspotLabels = append(commonAccountLabels, "hotspot", "hotspot_name")
|
|
|
|
|
|
|
|
|
|
// exporter metrics
|
|
|
|
|
|
|
|
|
|
// helium oracle metrics
|
|
|
|
@ -41,7 +48,7 @@ var (
|
|
|
|
|
statsValidators = metricInfo{
|
|
|
|
|
prometheus.NewDesc(
|
|
|
|
|
prometheus.BuildFQName(namespace, "stats", "validators"),
|
|
|
|
|
"The number of hotspots.",
|
|
|
|
|
"The number of validators.",
|
|
|
|
|
nil, nil,
|
|
|
|
|
),
|
|
|
|
|
prometheus.GaugeValue,
|
|
|
|
@ -120,6 +127,46 @@ var (
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// helium account metrics
|
|
|
|
|
accountBalanceHnt = metricInfo{
|
|
|
|
|
prometheus.NewDesc(
|
|
|
|
|
prometheus.BuildFQName(namespace, "account", "balance_hnt"),
|
|
|
|
|
"The number of HNT token owned by the account.",
|
|
|
|
|
commonAccountLabels, nil,
|
|
|
|
|
),
|
|
|
|
|
prometheus.GaugeValue,
|
|
|
|
|
}
|
|
|
|
|
accountActivity = metricInfo{
|
|
|
|
|
prometheus.NewDesc(
|
|
|
|
|
prometheus.BuildFQName(namespace, "account", "activity_total"),
|
|
|
|
|
"The total number of time an activity occurred in an account.",
|
|
|
|
|
append(commonAccountLabels, "type"), nil,
|
|
|
|
|
),
|
|
|
|
|
prometheus.CounterValue,
|
|
|
|
|
}
|
|
|
|
|
accountRewardsHnt = metricInfo{
|
|
|
|
|
prometheus.NewDesc(
|
|
|
|
|
prometheus.BuildFQName(namespace, "account", "reward_hnt"),
|
|
|
|
|
"The number of HNT token rewarded to this account.",
|
|
|
|
|
commonAccountLabels, nil,
|
|
|
|
|
),
|
|
|
|
|
prometheus.GaugeValue,
|
|
|
|
|
}
|
|
|
|
|
accountDepositsHnt = metricInfo{
|
|
|
|
|
prometheus.NewDesc(
|
|
|
|
|
prometheus.BuildFQName(namespace, "account", "deposits_hnt_total"),
|
|
|
|
|
"The number of HNT token deposited to this account.",
|
|
|
|
|
commonAccountLabels, nil,
|
|
|
|
|
),
|
|
|
|
|
prometheus.CounterValue,
|
|
|
|
|
}
|
|
|
|
|
accountWithdrawalsHnt = metricInfo{
|
|
|
|
|
prometheus.NewDesc(
|
|
|
|
|
prometheus.BuildFQName(namespace, "account", "withdrawals_hnt_total"),
|
|
|
|
|
"The number of HNT token withdrawn from this account.",
|
|
|
|
|
commonAccountLabels, nil,
|
|
|
|
|
),
|
|
|
|
|
prometheus.CounterValue,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// helium hotspot metrics
|
|
|
|
|
)
|
|
|
|
@ -139,6 +186,12 @@ func (e *Exporter) Describe(ch chan<- *prometheus.Desc) {
|
|
|
|
|
ch <- statsCountries.Desc
|
|
|
|
|
ch <- statsHotspots.Desc
|
|
|
|
|
ch <- statsTokenSupply.Desc
|
|
|
|
|
|
|
|
|
|
ch <- accountBalanceHnt.Desc
|
|
|
|
|
ch <- accountActivity.Desc
|
|
|
|
|
ch <- accountRewardsHnt.Desc
|
|
|
|
|
ch <- accountDepositsHnt.Desc
|
|
|
|
|
ch <- accountWithdrawalsHnt.Desc
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Collect fetches the data from the helium blockchain api and delivers them as Prometheus metrics.
|
|
|
|
@ -146,8 +199,12 @@ func (e *Exporter) Describe(ch chan<- *prometheus.Desc) {
|
|
|
|
|
func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
|
|
|
|
|
e.collectOracleMetrics(ch)
|
|
|
|
|
e.collectStatsMetrics(ch)
|
|
|
|
|
for _, account := range e.Accounts {
|
|
|
|
|
e.collectAccountMetrics(ch, account)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// collectOracleMetrics collect metrics in the oracle group from the helium api
|
|
|
|
|
func (e *Exporter) collectOracleMetrics(ch chan<- prometheus.Metric) {
|
|
|
|
|
currentOraclePrice, err := heliumapi.GetCurrentOraclePrice()
|
|
|
|
|
if err != nil {
|
|
|
|
@ -160,6 +217,7 @@ func (e *Exporter) collectOracleMetrics(ch chan<- prometheus.Metric) {
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// collectStatsMetrics collect metrics in the stats group from the helium api
|
|
|
|
|
func (e *Exporter) collectStatsMetrics(ch chan<- prometheus.Metric) {
|
|
|
|
|
blockchainStats, err := heliumapi.GetBlockchainStats()
|
|
|
|
|
if err != nil {
|
|
|
|
@ -199,15 +257,41 @@ func (e *Exporter) collectStatsMetrics(ch chan<- prometheus.Metric) {
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// collectStatsMetrics collect metrics in the account group from the helium api
|
|
|
|
|
func (e *Exporter) collectAccountMetrics(ch chan<- prometheus.Metric, account string) {
|
|
|
|
|
accountForAddress, err := heliumapi.GetAccountForAddress(account)
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Println(err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ch <- prometheus.MustNewConstMetric(
|
|
|
|
|
accountBalanceHnt.Desc, accountBalanceHnt.Type, float64(accountForAddress.Data.Balance),
|
|
|
|
|
account,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NewExporter returns an initialized Exporter
|
|
|
|
|
func NewExporter() (*Exporter, error) {
|
|
|
|
|
return &Exporter{}, nil
|
|
|
|
|
func NewExporter(accounts []string) (*Exporter, error) {
|
|
|
|
|
return &Exporter{
|
|
|
|
|
Accounts: accounts,
|
|
|
|
|
}, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
|
metricsPath := "/metrics"
|
|
|
|
|
fHeliumAccounts := flag.String("accounts", "", "A comma-delimited list of helium accounts to scrape.")
|
|
|
|
|
fMetricsPath := flag.String("metricpath", "/metrics", "The metrics path")
|
|
|
|
|
fListenAddress := flag.String("listenAddress", "0.0.0.0", "The http server listen address")
|
|
|
|
|
fListenPort := flag.String("listenPort", "9111", "The http server listen port")
|
|
|
|
|
flag.Parse()
|
|
|
|
|
|
|
|
|
|
e, err := NewExporter()
|
|
|
|
|
heliumAccounts := make([]string, 0)
|
|
|
|
|
if *fHeliumAccounts != "" {
|
|
|
|
|
heliumAccounts = strings.Split(*fHeliumAccounts, ",")
|
|
|
|
|
}
|
|
|
|
|
serverAddr := *fListenAddress + ":" + *fListenPort
|
|
|
|
|
|
|
|
|
|
e, err := NewExporter(heliumAccounts)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatalf("failed to start exporter: %s", err.Error())
|
|
|
|
|
}
|
|
|
|
@ -221,11 +305,12 @@ func main() {
|
|
|
|
|
<head><title>Helium blockchain exporter</title></head>
|
|
|
|
|
<body>
|
|
|
|
|
<h1>Helium blockchain exporter</h1>
|
|
|
|
|
<p><a href='` + metricsPath + `'>Metrics</a></p>
|
|
|
|
|
<p><a href='` + *fMetricsPath + `'>Metrics</a></p>
|
|
|
|
|
</body>
|
|
|
|
|
</html>`))
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
http.Handle(metricsPath, promhttp.HandlerFor(r, promhttp.HandlerOpts{}))
|
|
|
|
|
http.ListenAndServe(":9111", nil)
|
|
|
|
|
http.Handle(*fMetricsPath, promhttp.HandlerFor(r, promhttp.HandlerOpts{}))
|
|
|
|
|
fmt.Printf("exporter listening on %v\n", serverAddr)
|
|
|
|
|
http.ListenAndServe(serverAddr, nil)
|
|
|
|
|
}
|
|
|
|
|