@@ -3,11 +3,32 @@ package collectors
33import (
44 "context"
55 "fmt"
6+ "math"
67
78 "github.com/lightninglabs/lndclient"
89 "github.com/prometheus/client_golang/prometheus"
910)
1011
12+ const (
13+ // inboundFeeFeatureBits is the feature id used to advertise inbound
14+ // fees in gossip TLV extensions.
15+ inboundFeeFeatureBits = 55555
16+
17+ // Define some collector names and help texts for inbound fees.
18+ inboundFeeRateName = "lnd_graph_inbound_fee_rate_msat_histogram"
19+ inboundFeeBaseName = "lnd_graph_inbound_fee_base_msat_histogram"
20+ inboundFeeRateHelp = "histogram of inbound fee rates for channel " +
21+ "routing policies in msat"
22+ inboundFeeBaseHelp = "histogram of inbound base fees for channel " +
23+ "routing policies in msat"
24+
25+ // Define labels to categorize inbound fees into negative and positive
26+ // buckets.
27+ inboundFeeSignLabel = "sign"
28+ inboundFeeSignLabelPositive = "positive"
29+ inboundFeeSignLabelNegative = "negative"
30+ )
31+
1132// GraphCollector is a collector that keeps track of graph information.
1233type GraphCollector struct {
1334 numEdgesDesc * prometheus.Desc
@@ -46,6 +67,9 @@ type GraphCollector struct {
4667 minFeeRateMsatDesc * prometheus.Desc
4768 avgFeeRateMsatDesc * prometheus.Desc
4869
70+ inboundFeeBaseMsatDesc * prometheus.Desc
71+ inboundFeeRateMsatDesc * prometheus.Desc
72+
4973 medianMaxHtlcMsatDesc * prometheus.Desc
5074 maxMaxHtlcMsatDesc * prometheus.Desc
5175 minMaxHtlcMsatDesc * prometheus.Desc
@@ -207,6 +231,15 @@ func NewGraphCollector(lnd lndclient.LightningClient,
207231 nil , nil ,
208232 ),
209233
234+ inboundFeeBaseMsatDesc : prometheus .NewDesc (
235+ inboundFeeBaseName , inboundFeeBaseHelp ,
236+ []string {inboundFeeSignLabel }, nil ,
237+ ),
238+ inboundFeeRateMsatDesc : prometheus .NewDesc (
239+ inboundFeeRateName , inboundFeeRateHelp ,
240+ []string {inboundFeeSignLabel }, nil ,
241+ ),
242+
210243 medianMaxHtlcMsatDesc : prometheus .NewDesc (
211244 "lnd_graph_max_htlc_msat_median" ,
212245 "median max htlc for a channel routing policy in msat" ,
@@ -274,6 +307,9 @@ func (g *GraphCollector) Describe(ch chan<- *prometheus.Desc) {
274307 ch <- g .avgFeeRateMsatDesc
275308 ch <- g .medianFeeRateMsatDesc
276309
310+ ch <- g .inboundFeeBaseMsatDesc
311+ ch <- g .inboundFeeRateMsatDesc
312+
277313 ch <- g .minMaxHtlcMsatDesc
278314 ch <- g .maxMaxHtlcMsatDesc
279315 ch <- g .avgMaxHtlcMsatDesc
@@ -366,6 +402,27 @@ func (g *GraphCollector) collectRoutingPolicyMetrics(
366402
367403 feeBaseStats = newStatsCompiler (numEdges )
368404 feeRateStats = newStatsCompiler (numEdges )
405+
406+ inboundFeeBaseStats = prometheus .NewHistogramVec (
407+ prometheus.HistogramOpts {
408+ Name : inboundFeeBaseName ,
409+ Help : inboundFeeBaseHelp ,
410+ Buckets : prometheus .ExponentialBuckets (
411+ 1 , 2 , 20 , // 1 to 1_048_576 msat
412+ ),
413+ },
414+ []string {inboundFeeSignLabel },
415+ )
416+ inboundFeeRateStats = prometheus .NewHistogramVec (
417+ prometheus.HistogramOpts {
418+ Name : inboundFeeRateName ,
419+ Help : inboundFeeRateHelp ,
420+ Buckets : prometheus .ExponentialBuckets (
421+ 1 , 2 , 15 , // 1 to 32768 PPM ~ 3 %
422+ ),
423+ },
424+ []string {inboundFeeSignLabel },
425+ )
369426 )
370427
371428 for _ , edge := range edges {
@@ -385,6 +442,36 @@ func (g *GraphCollector) collectRoutingPolicyMetrics(
385442
386443 feeBaseStats .Observe (float64 (policy .FeeBaseMsat ))
387444 feeRateStats .Observe (float64 (policy .FeeRateMilliMsat ))
445+
446+ // Collect optional non-zero inbound fee statistics.
447+ _ , ok := policy .CustomRecords [inboundFeeFeatureBits ]
448+ if ok {
449+ absBase := math .Abs (float64 (
450+ policy .InboundBaseFeeMsat ,
451+ ))
452+ if policy .InboundBaseFeeMsat < 0 {
453+ inboundFeeBaseStats .WithLabelValues (
454+ inboundFeeSignLabelNegative ,
455+ ).Observe (absBase )
456+ } else if policy .InboundBaseFeeMsat > 0 {
457+ inboundFeeBaseStats .WithLabelValues (
458+ inboundFeeSignLabelPositive ,
459+ ).Observe (absBase )
460+ }
461+
462+ absRate := math .Abs (
463+ float64 (policy .InboundFeeRatePPM ),
464+ )
465+ if policy .InboundFeeRatePPM < 0 {
466+ inboundFeeRateStats .WithLabelValues (
467+ inboundFeeSignLabelNegative ,
468+ ).Observe (absRate )
469+ } else if policy .InboundFeeRatePPM > 0 {
470+ inboundFeeRateStats .WithLabelValues (
471+ inboundFeeSignLabelPositive ,
472+ ).Observe (absRate )
473+ }
474+ }
388475 }
389476 }
390477
@@ -478,4 +565,7 @@ func (g *GraphCollector) collectRoutingPolicyMetrics(
478565 g .medianFeeRateMsatDesc , prometheus .GaugeValue ,
479566 feeRateReport .median ,
480567 )
568+
569+ inboundFeeBaseStats .Collect (ch )
570+ inboundFeeRateStats .Collect (ch )
481571}
0 commit comments