1
0
Fork 0

add hotspot activity and rewards metrics

This commit is contained in:
Massaki Archambault 2021-09-17 16:45:01 -04:00
parent cc251b1041
commit 7f8b73055e
3 changed files with 128 additions and 60 deletions

View File

@ -27,15 +27,14 @@ type Exporter struct {
// Account represents a helium account
type Account struct {
hotspots []Hotspot
hash string
lastRewardsUpdate time.Time
hotspots []Hotspot
hash string
}
// Hotspot represent a helium hotspot
type Hotspot struct {
hash string
lastRewardsUpdate time.Time
name string
hash string
}
const (
@ -160,11 +159,11 @@ var (
}
accountRewardsHnt = metricInfo{
prometheus.NewDesc(
prometheus.BuildFQName(namespace, "account", "rewards_hnt"),
prometheus.BuildFQName(namespace, "account", "rewards_hnt_total"),
"The number of HNT token rewarded to an account.",
commonAccountLabels, nil,
),
prometheus.GaugeValue,
prometheus.CounterValue,
}
// accountDepositsHnt = metricInfo{
// prometheus.NewDesc(
@ -192,25 +191,25 @@ var (
),
prometheus.GaugeValue,
}
hotspotListening = metricInfo{
hotspotRelayed = metricInfo{
prometheus.NewDesc(
prometheus.BuildFQName(namespace, "hotspot", "listening"),
"Whether a hotspot is listening (not relayed).",
prometheus.BuildFQName(namespace, "hotspot", "relayed"),
"Whether a hotspot is relayed.",
commonHotspotLabels, nil,
),
prometheus.GaugeValue,
}
hotspotBlockHeight = metricInfo{
hotspotBlocks = metricInfo{
prometheus.NewDesc(
prometheus.BuildFQName(namespace, "hotspot", "block_height"),
"The block height of a Hotspot. Check on the hotspot itself for the most recent data.",
prometheus.BuildFQName(namespace, "hotspot", "blocks_total"),
"The block height of a hotspot. Check on the hotspot itself for the most recent data.",
commonHotspotLabels, nil,
),
prometheus.CounterValue,
}
hotspotRewardScale = metricInfo{
hotspotRewardsScale = metricInfo{
prometheus.NewDesc(
prometheus.BuildFQName(namespace, "hotspot", "reward_scale"),
prometheus.BuildFQName(namespace, "hotspot", "rewards_scale"),
"The reward scale of a hotspot.",
commonHotspotLabels, nil,
),
@ -227,7 +226,7 @@ var (
hotspotAntennaInfo = metricInfo{
prometheus.NewDesc(
prometheus.BuildFQName(namespace, "hotspot", "antenna_info"),
"Information on the location of a hotspot.",
"Information on the antenna of a hotspot.",
append(commonHotspotLabels, "gain", "elevation"), nil,
),
prometheus.GaugeValue,
@ -242,11 +241,11 @@ var (
}
hotspotRewardsHnt = metricInfo{
prometheus.NewDesc(
prometheus.BuildFQName(namespace, "hotspot", "rewards_hnt"),
prometheus.BuildFQName(namespace, "hotspot", "rewards_hnt_total"),
"The number of HNT token rewarded to a hotspot.",
commonHotspotLabels, nil,
),
prometheus.GaugeValue,
prometheus.CounterValue,
}
)
@ -280,9 +279,9 @@ func (e *Exporter) Describe(ch chan<- *prometheus.Desc) {
// ch <- accountWithdrawalsHnt.Desc
ch <- hotspotUp.Desc
ch <- hotspotListening.Desc
ch <- hotspotBlockHeight.Desc
ch <- hotspotRewardScale.Desc
ch <- hotspotRelayed.Desc
ch <- hotspotBlocks.Desc
ch <- hotspotRewardsScale.Desc
ch <- hotspotGeocodeInfo.Desc
ch <- hotspotAntennaInfo.Desc
ch <- hotspotActivity.Desc
@ -294,9 +293,9 @@ 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)
e.collectHotspotMetrics(ch, &account)
for i := range e.Accounts {
e.collectAccountMetrics(ch, &e.Accounts[i])
e.collectHotspotMetrics(ch, &e.Accounts[i])
}
}
@ -367,7 +366,7 @@ func (e *Exporter) collectAccountMetrics(ch chan<- prometheus.Metric, account *A
return
}
accountRewardTotalsForAddress, err := heliumapi.GetRewardTotalsForAccount(account.hash, &account.lastRewardsUpdate, nil)
accountRewardTotalsForAddress, err := heliumapi.GetRewardTotalsForAccount(account.hash, &time.Time{}, nil)
if err != nil {
fmt.Println(err)
return
@ -387,10 +386,6 @@ func (e *Exporter) collectAccountMetrics(ch chan<- prometheus.Metric, account *A
accountRewardsHnt.Desc, accountRewardsHnt.Type, accountRewardTotalsForAddress.Data.Sum,
account.hash,
)
account.lastRewardsUpdate, err = time.Parse(time.RFC3339, accountRewardTotalsForAddress.Meta.MaxTime)
if err != nil {
fmt.Printf("failed to parse time \"%v\", value of %v will be bad: %v\n", accountRewardTotalsForAddress.Meta.MaxTime, accountRewardsHnt.Desc.String(), err)
}
}
// collectStatsMetrics collect metrics in the hotspot group from the helium api
@ -402,20 +397,32 @@ func (e *Exporter) collectHotspotMetrics(ch chan<- prometheus.Metric, account *A
}
for _, hotspotData := range hotspotsForAddress.Data {
hotspotActivityForAddress, err := heliumapi.GetHotspotActivityCount(hotspotData.Address)
if err != nil {
fmt.Println(err)
return
}
hotspotRewardTotalsForAddress, err := heliumapi.GetRewardsTotalForHotspot(hotspotData.Address, &time.Time{}, nil)
if err != nil {
fmt.Println(err)
return
}
ch <- prometheus.MustNewConstMetric(
hotspotUp.Desc, hotspotUp.Type, bool2Float64(hotspotData.Status.Online == "online"),
account.hash, hotspotData.Address, hotspotData.Name,
)
ch <- prometheus.MustNewConstMetric(
hotspotListening.Desc, hotspotListening.Type, bool2Float64(len(hotspotData.Status.ListenAddrs) != 0),
hotspotRelayed.Desc, hotspotRelayed.Type, bool2Float64(len(hotspotData.Status.ListenAddrs) > 0 && strings.HasPrefix(hotspotData.Status.ListenAddrs[0], "/p2p")),
account.hash, hotspotData.Address, hotspotData.Name,
)
ch <- prometheus.MustNewConstMetric(
hotspotBlockHeight.Desc, hotspotBlockHeight.Type, float64(hotspotData.Status.Height),
hotspotBlocks.Desc, hotspotBlocks.Type, float64(hotspotData.Status.Height),
account.hash, hotspotData.Address, hotspotData.Name,
)
ch <- prometheus.MustNewConstMetric(
hotspotRewardScale.Desc, hotspotRewardScale.Type, float64(hotspotData.RewardScale),
hotspotRewardsScale.Desc, hotspotRewardsScale.Type, float64(hotspotData.RewardScale),
account.hash, hotspotData.Address, hotspotData.Name,
)
ch <- prometheus.MustNewConstMetric(
@ -426,6 +433,16 @@ func (e *Exporter) collectHotspotMetrics(ch chan<- prometheus.Metric, account *A
hotspotAntennaInfo.Desc, hotspotAntennaInfo.Type, 1.0,
account.hash, hotspotData.Address, hotspotData.Name, strconv.Itoa(hotspotData.Gain), strconv.Itoa(hotspotData.Elevation),
)
for accType, count := range hotspotActivityForAddress.Data {
ch <- prometheus.MustNewConstMetric(
hotspotActivity.Desc, hotspotActivity.Type, float64(count),
account.hash, hotspotData.Address, hotspotData.Name, accType,
)
}
ch <- prometheus.MustNewConstMetric(
hotspotRewardsHnt.Desc, hotspotRewardsHnt.Type, hotspotRewardTotalsForAddress.Data.Sum,
account.hash, hotspotData.Address, hotspotData.Name,
)
}
}
@ -444,8 +461,7 @@ func NewExporter(accountHashs []string) (*Exporter, error) {
func NewAccount(hash string) Account {
return Account{
hash: hash,
lastRewardsUpdate: time.Now(),
hash: hash,
}
}

View File

@ -19,37 +19,16 @@ type Account struct {
} `json:"data"`
}
type ActivityCounts struct {
Data map[string]int
}
type RewardTotal struct {
Meta struct {
MinTime string `json:"min_time"`
MaxTime string `json:"max_time"`
} `json:"meta"`
Data struct {
Total float64 `json:"total"`
Sum float64 `json:"sum"`
Stddev float64 `json:"stddev"`
Min float64 `json:"min"`
Median float64 `json:"median"`
Max float64 `json:"max"`
Avg float64 `json:"avg"`
} `json:"data"`
}
type AccountHotspots struct {
Data []struct {
Lng float64 `json:"lng"`
Lat float64 `json:"lat"`
TimestampAdded string `json:"timestamp_added"`
Status struct {
Timestamp string `json:"timestamp"`
Online string `json:"online"`
ListenAddrs []string
Height int
Timestamp string `json:"timestamp"`
Online string `json:"online"`
ListenAddrs []string `json:"listen_addrs"`
Height int `json:"height"`
} `json:"status"`
RewardScale float64 `json:"reward_scale"`
Payer string `json:"payer"`
@ -125,7 +104,7 @@ func GetRewardTotalsForAccount(account string, minTime *time.Time, maxTime *time
params["min_time"] = minTime.UTC().Format("2006-01-02T15:04:05Z")
}
if maxTime != nil {
params["max_time"] = minTime.UTC().Format("2006-01-02T15:04:05Z")
params["max_time"] = maxTime.UTC().Format("2006-01-02T15:04:05Z")
}
// query the api

73
heliumapi/hotspots.go Normal file
View File

@ -0,0 +1,73 @@
package heliumapi
import (
"encoding/json"
"fmt"
"time"
)
type ActivityCounts struct {
Data map[string]int
}
type RewardTotal struct {
Meta struct {
MinTime string `json:"min_time"`
MaxTime string `json:"max_time"`
} `json:"meta"`
Data struct {
Total float64 `json:"total"`
Sum float64 `json:"sum"`
Stddev float64 `json:"stddev"`
Min float64 `json:"min"`
Median float64 `json:"median"`
Max float64 `json:"max"`
Avg float64 `json:"avg"`
} `json:"data"`
}
func GetHotspotActivityCount(hotspot string) (*ActivityCounts, error) {
path := "/v1/hotspots/" + hotspot + "/activity/count"
// query the api
respBody, err := getHeliumApi(path, nil)
if err != nil {
return nil, err
}
// unmarshal the response
respobject := ActivityCounts{}
err = json.Unmarshal(respBody, &respobject)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal response from path %v: %v", path, err)
}
return &respobject, nil
}
func GetRewardsTotalForHotspot(hotspot string, minTime *time.Time, maxTime *time.Time) (*RewardTotal, error) {
path := "/v1/hotspots/" + hotspot + "/rewards/sum"
params := map[string]string{}
if minTime != nil {
params["min_time"] = minTime.UTC().Format("2006-01-02T15:04:05Z")
}
if maxTime != nil {
params["max_time"] = maxTime.UTC().Format("2006-01-02T15:04:05Z")
}
// query the api
respBody, err := getHeliumApi(path, &params)
if err != nil {
return nil, err
}
// unmarshal the response
respobject := RewardTotal{}
err = json.Unmarshal(respBody, &respobject)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal response from path %v: %v", path, err)
}
return &respobject, nil
}