-
Notifications
You must be signed in to change notification settings - Fork 49
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
collectors: collect payment and attempt counts
collect raw payment and attempt count information from lnd using the TrackPayments RPC.
- Loading branch information
1 parent
98a89e9
commit 0cf9fd4
Showing
5 changed files
with
200 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
package collectors | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"sync" | ||
|
||
"github.com/lightninglabs/lndclient" | ||
"github.com/lightningnetwork/lnd/lnrpc" | ||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc" | ||
"github.com/prometheus/client_golang/prometheus" | ||
) | ||
|
||
var ( | ||
totalPayments = prometheus.NewCounter( | ||
prometheus.CounterOpts{ | ||
Name: "lnd_total_payments", | ||
Help: "Total number of payments initiated", | ||
}, | ||
) | ||
totalHTLCAttempts = prometheus.NewCounter( | ||
prometheus.CounterOpts{ | ||
Name: "lnd_total_htlc_attempts", | ||
Help: "Total number of HTLC attempts across all payments", | ||
}, | ||
) | ||
paymentAttempts = prometheus.NewHistogram( | ||
prometheus.HistogramOpts{ | ||
Name: "lnd_payment_attempts_per_payment", | ||
Help: "Histogram tracking the number of attempts per payment", | ||
Buckets: prometheus.LinearBuckets(1, 1, 10), // 1 to 10 attempts | ||
}, | ||
) | ||
) | ||
|
||
// paymentsMonitor listens for payments and updates Prometheus metrics. | ||
type paymentsMonitor struct { | ||
client routerrpc.RouterClient | ||
|
||
ctx context.Context | ||
|
||
errChan chan error | ||
|
||
// quit is closed to signal that we need to shutdown. | ||
quit chan struct{} | ||
|
||
wg sync.WaitGroup | ||
} | ||
|
||
// newPaymentsMonitor creates a new payments monitor and ensures the context | ||
// includes macaroon authentication. | ||
func newPaymentsMonitor(lnd *lndclient.LndServices, | ||
errChan chan error) (*paymentsMonitor, error) { | ||
|
||
// Attach macaroon authentication for the router service. | ||
ctx := context.Background() | ||
ctx, err := lnd.WithMacaroonAuthForService(ctx, | ||
lndclient.RouterServiceMac) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to get macaroon-authenticated "+ | ||
"context: %w", err) | ||
} | ||
|
||
return &paymentsMonitor{ | ||
client: routerrpc.NewRouterClient(lnd.ClientConn), | ||
errChan: errChan, | ||
quit: make(chan struct{}), | ||
ctx: ctx, | ||
}, nil | ||
} | ||
|
||
// start subscribes to `TrackPayments` and updates Prometheus metrics. | ||
func (p *paymentsMonitor) start() error { | ||
// Use the stored authenticated context. | ||
ctx, cancel := context.WithCancel(p.ctx) | ||
|
||
paymentLogger.Info("Starting payments monitor...") | ||
|
||
stream, err := p.client.TrackPayments(ctx, | ||
&routerrpc.TrackPaymentsRequest{ | ||
// NOTE: We only need to know the final result of the | ||
// payment and all attempts. | ||
NoInflightUpdates: true, | ||
}) | ||
if err != nil { | ||
paymentLogger.Errorf("Failed to subscribe to TrackPayments: %v", | ||
err) | ||
|
||
cancel() | ||
|
||
return err | ||
} | ||
|
||
p.wg.Add(1) | ||
go func() { | ||
defer func() { | ||
cancel() | ||
p.wg.Done() | ||
}() | ||
|
||
for { | ||
select { | ||
case <-p.quit: | ||
return | ||
|
||
default: | ||
payment, err := stream.Recv() | ||
if err != nil { | ||
paymentLogger.Errorf("Error receiving "+ | ||
"payment update: %v", err) | ||
|
||
p.errChan <- err | ||
return | ||
} | ||
processPaymentUpdate(payment) | ||
} | ||
} | ||
}() | ||
|
||
return nil | ||
} | ||
|
||
// stop cancels the payments monitor subscription. | ||
func (p *paymentsMonitor) stop() { | ||
paymentLogger.Info("Stopping payments monitor...") | ||
|
||
close(p.quit) | ||
p.wg.Wait() | ||
} | ||
|
||
// collectors returns all of the collectors that the htlc monitor uses. | ||
func (p *paymentsMonitor) collectors() []prometheus.Collector { | ||
return []prometheus.Collector{ | ||
totalPayments, totalHTLCAttempts, paymentAttempts, | ||
} | ||
} | ||
|
||
// processPaymentUpdate updates Prometheus metrics based on received payments. | ||
// | ||
// NOTE: It is expected that this receive the *final* payment update with the | ||
// complete list of all htlc attempts made for this payment. | ||
func processPaymentUpdate(payment *lnrpc.Payment) { | ||
totalPayments.Inc() | ||
attemptCount := len(payment.Htlcs) | ||
|
||
totalHTLCAttempts.Add(float64(attemptCount)) | ||
paymentAttempts.Observe(float64(attemptCount)) | ||
|
||
paymentLogger.Debugf("Payment %s updated: %d attempts", | ||
payment.PaymentHash, attemptCount) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters