mirror of
https://github.com/aljazceru/plugins.git
synced 2025-12-19 14:14:20 +01:00
240 lines
8.4 KiB
Python
Executable File
240 lines
8.4 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
from pyln.client import Plugin
|
|
from prometheus_client import start_http_server, CollectorRegistry
|
|
from prometheus_client.core import InfoMetricFamily, GaugeMetricFamily
|
|
from sys import exit
|
|
|
|
plugin = Plugin()
|
|
|
|
|
|
class BaseLnCollector(object):
|
|
def __init__(self, rpc, registry):
|
|
self.rpc = rpc
|
|
self.registry = registry
|
|
|
|
|
|
class NodeCollector(BaseLnCollector):
|
|
def collect(self):
|
|
info = self.rpc.getinfo()
|
|
info_labels = {k.replace('-', '_'): v for k, v in info.items() if isinstance(v, str)}
|
|
node_info_fam = InfoMetricFamily(
|
|
'lightning_node',
|
|
'Static node information',
|
|
labels=info_labels.keys(),
|
|
)
|
|
node_info_fam.add_metric(info_labels, info_labels)
|
|
yield node_info_fam
|
|
|
|
blockheight = info['blockheight']
|
|
yield GaugeMetricFamily(
|
|
'lightning_node_blockheight',
|
|
"Current Bitcoin blockheight on this node.",
|
|
value=blockheight,
|
|
)
|
|
|
|
fees_msat = int(info.get(
|
|
"fees_collected_msat",
|
|
info.get("msatoshi_fees_collected", None)
|
|
))
|
|
yield GaugeMetricFamily(
|
|
'lightning_fees_collected_msat',
|
|
'How much have we been paid to route payments?',
|
|
value=fees_msat,
|
|
)
|
|
|
|
|
|
class FundsCollector(BaseLnCollector):
|
|
def collect(self):
|
|
funds = self.rpc.listfunds()
|
|
print(funds['outputs'])
|
|
output_funds = sum(
|
|
[o['amount_msat'].to_satoshi() for o in funds['outputs']]
|
|
)
|
|
channel_funds = sum(
|
|
[c['our_amount_msat'].to_satoshi() for c in funds['channels']]
|
|
)
|
|
total = output_funds + channel_funds
|
|
|
|
yield GaugeMetricFamily(
|
|
'lightning_funds_total',
|
|
"Total satoshis we own on this node.",
|
|
value=total,
|
|
)
|
|
yield GaugeMetricFamily(
|
|
'lightning_funds_output',
|
|
"On-chain satoshis at our disposal",
|
|
value=output_funds,
|
|
)
|
|
yield GaugeMetricFamily(
|
|
'lightning_funds_channel',
|
|
"Satoshis in channels.",
|
|
value=channel_funds,
|
|
)
|
|
|
|
|
|
class PeerCollector(BaseLnCollector):
|
|
def collect(self):
|
|
peers = self.rpc.listpeers()['peers']
|
|
|
|
connected = GaugeMetricFamily(
|
|
'lightning_peer_connected',
|
|
'Is the peer currently connected?',
|
|
labels=['id'],
|
|
)
|
|
count = GaugeMetricFamily(
|
|
'lightning_peer_channels',
|
|
"The number of channels with the peer",
|
|
labels=['id'],
|
|
)
|
|
|
|
channels = self.rpc.listpeerchannels()['channels']
|
|
# Associate each channel with a peer
|
|
peers = {}
|
|
conn = {}
|
|
for c in channels:
|
|
peer_id = c['peer_id']
|
|
peers[peer_id] = peers.get(peer_id, 0) + 1
|
|
conn[peer_id] = conn.get(peer_id, 0) + c['peer_connected']
|
|
|
|
for p in peers.keys():
|
|
labels = [p]
|
|
count.add_metric(labels, peers[p])
|
|
connected.add_metric(labels, conn.get(p, 0))
|
|
|
|
return [count, connected]
|
|
|
|
|
|
class ChannelsCollector(BaseLnCollector):
|
|
def collect(self):
|
|
balance_gauge = GaugeMetricFamily(
|
|
'lightning_channel_balance',
|
|
'How many funds are at our disposal?',
|
|
labels=['id', 'scid', 'alias'],
|
|
)
|
|
spendable_gauge = GaugeMetricFamily(
|
|
'lightning_channel_spendable',
|
|
'How much can we currently send over this channel?',
|
|
labels=['id', 'scid', 'alias'],
|
|
)
|
|
total_gauge = GaugeMetricFamily(
|
|
'lightning_channel_capacity',
|
|
'How many funds are in this channel in total?',
|
|
labels=['id', 'scid', 'alias'],
|
|
)
|
|
htlc_gauge = GaugeMetricFamily(
|
|
'lightning_channel_htlcs',
|
|
'How many HTLCs are currently active on this channel?',
|
|
labels=['id', 'scid', 'alias'],
|
|
)
|
|
|
|
# Incoming routing statistics
|
|
in_payments_offered_gauge = GaugeMetricFamily(
|
|
'lightning_channel_in_payments_offered',
|
|
'How many incoming payments did we try to forward?',
|
|
labels=['id', 'scid', 'alias'],
|
|
)
|
|
in_payments_fulfilled_gauge = GaugeMetricFamily(
|
|
'lightning_channel_in_payments_fulfilled',
|
|
'How many incoming payments did we succeed to forward?',
|
|
labels=['id', 'scid', 'alias'],
|
|
)
|
|
in_msatoshi_offered_gauge = GaugeMetricFamily(
|
|
'lightning_channel_in_msatoshi_offered',
|
|
'How many incoming msats did we try to forward?',
|
|
labels=['id', 'scid', 'alias'],
|
|
)
|
|
in_msatoshi_fulfilled_gauge = GaugeMetricFamily(
|
|
'lightning_channel_in_msatoshi_fulfilled',
|
|
'How many incoming msats did we succeed to forward?',
|
|
labels=['id', 'scid', 'alias'],
|
|
)
|
|
|
|
# Outgoing routing statistics
|
|
out_payments_offered_gauge = GaugeMetricFamily(
|
|
'lightning_channel_out_payments_offered',
|
|
'How many outgoing payments did we try to forward?',
|
|
labels=['id', 'scid', 'alias'],
|
|
)
|
|
out_payments_fulfilled_gauge = GaugeMetricFamily(
|
|
'lightning_channel_out_payments_fulfilled',
|
|
'How many outgoing payments did we succeed to forward?',
|
|
labels=['id', 'scid', 'alias'],
|
|
)
|
|
out_msatoshi_offered_gauge = GaugeMetricFamily(
|
|
'lightning_channel_out_msatoshi_offered',
|
|
'How many outgoing msats did we try to forward?',
|
|
labels=['id', 'scid', 'alias'],
|
|
)
|
|
out_msatoshi_fulfilled_gauge = GaugeMetricFamily(
|
|
'lightning_channel_out_msatoshi_fulfilled',
|
|
'How many outgoing msats did we succeed to forward?',
|
|
labels=['id', 'scid', 'alias'],
|
|
)
|
|
|
|
channels = self.rpc.listpeerchannels()['channels']
|
|
for c in channels:
|
|
# append alias for human readable labels, if no label is found fill with shortid.
|
|
node = self.rpc.listnodes(c['peer_id'])['nodes']
|
|
if len(node) != 0 and 'alias' in node[0]:
|
|
alias = node[0]['alias']
|
|
else:
|
|
alias = 'unknown'
|
|
|
|
labels = [c['peer_id'], c.get('short_channel_id', c.get('channel_id')), alias]
|
|
balance_gauge.add_metric(labels, c['to_us_msat'].to_satoshi())
|
|
spendable_gauge.add_metric(labels,
|
|
c['spendable_msat'].to_satoshi())
|
|
total_gauge.add_metric(labels, c['total_msat'].to_satoshi())
|
|
htlc_gauge.add_metric(labels, len(c['htlcs']))
|
|
|
|
in_payments_offered_gauge.add_metric(labels, c['in_payments_offered'])
|
|
in_payments_fulfilled_gauge.add_metric(labels, c['in_payments_fulfilled'])
|
|
in_msatoshi_offered_gauge.add_metric(labels, int(c['in_offered_msat']))
|
|
in_msatoshi_fulfilled_gauge.add_metric(labels, int(c['in_fulfilled_msat']))
|
|
|
|
out_payments_offered_gauge.add_metric(labels, c['out_payments_offered'])
|
|
out_payments_fulfilled_gauge.add_metric(labels, c['out_payments_fulfilled'])
|
|
out_msatoshi_offered_gauge.add_metric(labels, int(c['out_offered_msat']))
|
|
out_msatoshi_fulfilled_gauge.add_metric(labels, int(c['out_fulfilled_msat']))
|
|
|
|
return [
|
|
htlc_gauge,
|
|
total_gauge,
|
|
spendable_gauge,
|
|
balance_gauge,
|
|
in_payments_offered_gauge,
|
|
in_payments_fulfilled_gauge,
|
|
in_msatoshi_offered_gauge,
|
|
in_msatoshi_fulfilled_gauge,
|
|
out_payments_offered_gauge,
|
|
out_payments_fulfilled_gauge,
|
|
out_msatoshi_offered_gauge,
|
|
out_msatoshi_fulfilled_gauge,
|
|
]
|
|
|
|
|
|
@plugin.init()
|
|
def init(options, configuration, plugin):
|
|
s = options['prometheus-listen'].rpartition(':')
|
|
if len(s) != 3 or s[1] != ':':
|
|
print("Could not parse prometheus-listen address")
|
|
exit(1)
|
|
ip, port = s[0], int(s[2])
|
|
|
|
registry = CollectorRegistry()
|
|
start_http_server(addr=ip, port=port, registry=registry)
|
|
registry.register(NodeCollector(plugin.rpc, registry))
|
|
registry.register(FundsCollector(plugin.rpc, registry))
|
|
registry.register(PeerCollector(plugin.rpc, registry))
|
|
registry.register(ChannelsCollector(plugin.rpc, registry))
|
|
|
|
|
|
plugin.add_option(
|
|
'prometheus-listen',
|
|
'127.0.0.1:9750',
|
|
'Address and port to bind to'
|
|
)
|
|
|
|
|
|
plugin.run()
|