Skip to content

Commit 8c7e85d

Browse files
author
Richard Patel
committed
add aggregated_price metric
1 parent 15242f1 commit 8c7e85d

File tree

3 files changed

+83
-30
lines changed

3 files changed

+83
-30
lines changed

main.go

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"context"
55
"flag"
66
"fmt"
7-
"math"
87
"net/http"
98
"strings"
109
"time"
@@ -120,35 +119,13 @@ func main() {
120119
})
121120

122121
// Send price updates to Prometheus.
122+
prices := priceScraper{
123+
productKeys: productKeys.pubkeys,
124+
publishKeys: publishKeys.pubkeys,
125+
}
123126
group.Go(func() error {
124127
for update := range updates {
125-
// Filter by product key.
126-
var knownProduct bool
127-
for _, product := range productKeys.pubkeys {
128-
if product == update.Product {
129-
knownProduct = true
130-
break
131-
}
132-
}
133-
if !knownProduct {
134-
continue
135-
}
136-
decimals := math.Pow10(int(update.Exponent))
137-
// Update price of each publisher.
138-
for _, publisher := range publishKeys.pubkeys {
139-
comp := update.GetComponent(&publisher)
140-
if comp != nil {
141-
metrics.PublisherSlot.
142-
WithLabelValues(update.Product.String(), publisher.String()).
143-
Set(float64(comp.Latest.PubSlot))
144-
metrics.PublisherPrice.
145-
WithLabelValues(update.Product.String(), publisher.String()).
146-
Set(float64(comp.Latest.Price) * decimals)
147-
metrics.PublisherConf.
148-
WithLabelValues(update.Product.String(), publisher.String()).
149-
Set(float64(comp.Latest.Conf) * decimals)
150-
}
151-
}
128+
prices.onUpdate(update)
152129
}
153130
return nil
154131
})

metrics/metrics.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,18 @@ var (
5555
Name: "publish_account_balance",
5656
Help: "SOL balance of Pyth publish account in lamports",
5757
}, []string{labelPublisher})
58+
AggPrice = factory.NewGaugeVec(prometheus.GaugeOpts{
59+
Namespace: promNamespace,
60+
Subsystem: promSubsystemOracle,
61+
Name: "aggregated_price",
62+
Help: "Last aggregated price of Pyth product",
63+
}, []string{labelProduct})
64+
AggConf = factory.NewGaugeVec(prometheus.GaugeOpts{
65+
Namespace: promNamespace,
66+
Subsystem: promSubsystemOracle,
67+
Name: "aggregated_conf_amount",
68+
Help: "Last aggregated conf of Pyth product",
69+
}, []string{labelProduct})
5870
PublisherPrice = factory.NewGaugeVec(prometheus.GaugeOpts{
5971
Namespace: promNamespace,
6072
Subsystem: promSubsystemOracle,
@@ -78,11 +90,11 @@ var (
7890
metricTxFeesTotal = factory.NewCounterVec(prometheus.CounterOpts{
7991
Namespace: promNamespace,
8092
Name: "tx_fees_total",
81-
Help: "Cumulative amount of SOL in lamports spent on Pyth publishing",
93+
Help: "Approximate amount of SOL in lamports spent on Pyth publishing",
8294
}, []string{labelPublisher})
8395
metricTxCount = factory.NewCounterVec(prometheus.CounterOpts{
8496
Namespace: promNamespace,
8597
Name: "txs_total",
86-
Help: "Number of Pyth transactions sent",
98+
Help: "Approximate number of Pyth transactions sent",
8799
}, []string{labelPublisher, labelTxStatus})
88100
)

price.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package main
2+
3+
import (
4+
"math"
5+
6+
"github.com/gagliardetto/solana-go"
7+
"go.blockdaemon.com/pyth_exporter/metrics"
8+
"go.blockdaemon.com/pyth_exporter/pyth"
9+
)
10+
11+
type priceScraper struct {
12+
productKeys []solana.PublicKey
13+
publishKeys []solana.PublicKey
14+
}
15+
16+
func (p *priceScraper) onUpdate(update pyth.PriceAccountUpdate) {
17+
if !p.isInteresting(update) {
18+
return
19+
}
20+
decimals := math.Pow10(int(update.Exponent))
21+
p.aggregate(&update.Product, &update.Agg, decimals)
22+
// Update price of each publisher.
23+
for _, publisher := range p.publishKeys {
24+
comp := update.GetComponent(&publisher)
25+
if comp != nil {
26+
p.component(&update.Product, &publisher, comp, decimals)
27+
}
28+
}
29+
}
30+
31+
func (p *priceScraper) isInteresting(update pyth.PriceAccountUpdate) bool {
32+
for _, product := range p.productKeys {
33+
if product == update.Product {
34+
return true
35+
}
36+
}
37+
return false
38+
}
39+
40+
// aggregate exports price as aggregated by the smart contract.
41+
func (p *priceScraper) aggregate(product *solana.PublicKey, agg *pyth.PriceInfo, decimals float64) {
42+
productStr := product.String()
43+
metrics.AggPrice.
44+
WithLabelValues(productStr).
45+
Set(float64(agg.Price) * decimals)
46+
metrics.AggConf.
47+
WithLabelValues(productStr).
48+
Set(float64(agg.Conf) * decimals)
49+
}
50+
51+
// component exports a price component (i.e. a price value published by an individual Pyth publisher).
52+
func (p *priceScraper) component(product *solana.PublicKey, publisher *solana.PublicKey, comp *pyth.PriceComp, decimals float64) {
53+
productStr := product.String()
54+
publisherStr := publisher.String()
55+
metrics.PublisherSlot.
56+
WithLabelValues(productStr, publisherStr).
57+
Set(float64(comp.Latest.PubSlot))
58+
metrics.PublisherPrice.
59+
WithLabelValues(productStr, publisherStr).
60+
Set(float64(comp.Latest.Price) * decimals)
61+
metrics.PublisherConf.
62+
WithLabelValues(productStr, publisherStr).
63+
Set(float64(comp.Latest.Conf) * decimals)
64+
}

0 commit comments

Comments
 (0)