monero-exporter/pkg/collector/collector_lastblock.go
Ciro S. Costa debdce3fb2 rework collector
this is a big refactor, essentially rewriting the custom collector from
scratch, and as such, creating a new dashboard based on the new metrics.

Signed-off-by: Ciro S. Costa <utxobr@protonmail.com>
2021-08-02 17:44:20 -04:00

301 lines
6.7 KiB
Go

package collector
import (
"context"
"fmt"
"github.com/prometheus/client_golang/prometheus"
"github.com/cirocosta/go-monero/pkg/constant"
"github.com/cirocosta/go-monero/pkg/rpc/daemon"
)
type LastBlockStatsCollector struct {
client *daemon.Client
metricsC chan<- prometheus.Metric
txns []*daemon.TransactionJSON
txnSizes []int
header daemon.BlockHeader
}
var _ CustomCollector = (*LastBlockStatsCollector)(nil)
func NewLastBlockStatsCollector(
client *daemon.Client, metricsC chan<- prometheus.Metric,
) *LastBlockStatsCollector {
return &LastBlockStatsCollector{
client: client,
metricsC: metricsC,
}
}
func (c *LastBlockStatsCollector) Name() string {
return "lastblock"
}
func (c *LastBlockStatsCollector) Collect(ctx context.Context) error {
err := c.fetchData(ctx)
if err != nil {
return fmt.Errorf("fetch last block data: %w", err)
}
c.collectBlockSize()
c.collectDifficulty()
c.collectFees()
c.collectHeight()
c.collectReward()
c.collectSubsidy()
c.collectTransactionsCount()
c.collectTransactionsFeePerKb()
c.collectTransactionsInputs()
c.collectTransactionsOutputs()
c.collectTransactionsSize()
return nil
}
func (c *LastBlockStatsCollector) fetchData(ctx context.Context) error {
lastBlockHeaderResp, err := c.client.GetLastBlockHeader(ctx)
if err != nil {
return fmt.Errorf("get last block header: %w", err)
}
lastBlockHash := lastBlockHeaderResp.BlockHeader.Hash
params := daemon.GetBlockRequestParameters{
Hash: lastBlockHash,
}
blockResp, err := c.client.GetBlock(ctx, params)
if err != nil {
return fmt.Errorf("get block '%s': %w", lastBlockHash, err)
}
blockJSON, err := blockResp.InnerJSON()
if err != nil {
return fmt.Errorf("block inner json: %w", err)
}
txnsResp, err := c.client.GetTransactions(ctx, blockJSON.TxHashes)
if err != nil {
return fmt.Errorf("get txns: %w", err)
}
txnSizes := make([]int, len(txnsResp.Txs))
for idx, t := range txnsResp.Txs {
txnSizes[idx] = len(t.AsHex) / 2
}
txns, err := txnsResp.GetTransactions()
if err != nil {
return fmt.Errorf("get transactions: %w", err)
}
c.txns = txns
c.txnSizes = txnSizes
c.header = blockResp.BlockHeader
return nil
}
func (c *LastBlockStatsCollector) collectBlockSize() {
desc := prometheus.NewDesc(
"monero_lastblock_size_bytes",
"total size of the last block",
nil, nil,
)
c.metricsC <- prometheus.MustNewConstMetric(
desc,
prometheus.GaugeValue,
float64(c.header.BlockSize),
)
}
func (c *LastBlockStatsCollector) collectDifficulty() {
desc := prometheus.NewDesc(
"monero_lastblock_difficulty",
"difficulty used for the last block",
nil, nil,
)
c.metricsC <- prometheus.MustNewConstMetric(
desc,
prometheus.GaugeValue,
float64(c.header.Difficulty),
)
}
func (c *LastBlockStatsCollector) collectFees() {
desc := prometheus.NewDesc(
"monero_lastblock_fees_monero",
"total amount of fees included in this block",
nil, nil,
)
c.metricsC <- prometheus.MustNewConstMetric(
desc,
prometheus.GaugeValue,
float64(c.gatherFees(c.txns))/constant.XMR,
)
}
func (c *LastBlockStatsCollector) collectHeight() {
desc := prometheus.NewDesc(
"monero_lastblock_height",
"height of the last block",
nil, nil,
)
c.metricsC <- prometheus.MustNewConstMetric(
desc,
prometheus.GaugeValue,
float64(c.header.Height),
)
}
func (c *LastBlockStatsCollector) collectReward() {
desc := prometheus.NewDesc(
"monero_lastblock_reward_monero",
"total amount of rewards granted in the last block "+
"(subsidy + fees)",
nil, nil,
)
c.metricsC <- prometheus.MustNewConstMetric(
desc,
prometheus.GaugeValue,
float64(c.header.Reward)/constant.XMR,
)
}
func (c *LastBlockStatsCollector) collectSubsidy() {
totalReward := float64(c.header.Reward)
fees := float64(c.gatherFees(c.txns))
subsidy := (totalReward - fees) / constant.XMR
desc := prometheus.NewDesc(
"monero_lastblock_subsidy_monero",
"newly minted monero for this block",
nil, nil,
)
c.metricsC <- prometheus.MustNewConstMetric(
desc,
prometheus.GaugeValue,
subsidy,
)
}
func (c *LastBlockStatsCollector) collectTransactionsCount() {
desc := prometheus.NewDesc(
"monero_lastblock_transactions",
"number of transactions seen in the last block",
nil, nil,
)
c.metricsC <- prometheus.MustNewConstMetric(
desc,
prometheus.GaugeValue,
float64(c.header.NumTxes),
)
}
func (c *LastBlockStatsCollector) collectTransactionsFeePerKb() {
summary := NewSummary()
for idx, txn := range c.txns {
fee := float64(txn.RctSignatures.Txnfee) / constant.MicroXMR
size := float64(c.txnSizes[idx]) / 1024
summary.Insert(fee / size)
}
c.metricsC <- prometheus.MustNewConstSummary(
prometheus.NewDesc(
"monero_lastblock_fees_micronero_per_kb",
"distribution of the feeperkb utilized for txns",
nil, nil,
),
summary.Count(), summary.Sum(), summary.Quantiles(),
)
}
func (c *LastBlockStatsCollector) collectTransactionsSize() {
summary := NewSummary()
for _, size := range c.txnSizes {
summary.Insert(float64(size))
}
c.metricsC <- prometheus.MustNewConstSummary(
prometheus.NewDesc(
"monero_lastblock_transactions_size_bytes",
"distribution of the size of the transactions included",
nil, nil,
),
summary.Count(), summary.Sum(), summary.Quantiles(),
)
}
func (c *LastBlockStatsCollector) collectTransactionsInputs() {
summary := NewSummary()
for _, txn := range c.txns {
summary.Insert(float64(len(txn.Vin)))
}
c.metricsC <- prometheus.MustNewConstSummary(
prometheus.NewDesc(
"monero_lastblock_transactions_inputs",
"distribution of inputs in the last block",
nil, nil,
),
summary.Count(), summary.Sum(), summary.Quantiles(),
)
}
func (c *LastBlockStatsCollector) collectTransactionsOutputs() {
summary := NewSummary()
for _, txn := range c.txns {
summary.Insert(float64(len(txn.Vout)))
}
c.metricsC <- prometheus.MustNewConstSummary(
prometheus.NewDesc(
"monero_lastblock_transactions_outputs",
"distribution of outputs in the last block",
nil, nil,
),
summary.Count(), summary.Sum(), summary.Quantiles(),
)
}
func (c *LastBlockStatsCollector) collectVersions() {
c.metricsC <- prometheus.MustNewConstMetric(
prometheus.NewDesc(
"monero_lastblock_version_major",
"major version of the block format",
nil, nil,
),
prometheus.GaugeValue,
float64(c.header.MajorVersion),
)
c.metricsC <- prometheus.MustNewConstMetric(
prometheus.NewDesc(
"monero_lastblock_version_minor",
"minor version of the block format",
nil, nil,
),
prometheus.GaugeValue,
float64(c.header.MinorVersion),
)
}
func (c *LastBlockStatsCollector) gatherFees(txns []*daemon.TransactionJSON) uint64 {
fees := uint64(0)
for _, txn := range txns {
fees += txn.RctSignatures.Txnfee
}
return fees
}