Expose Logos node metrics to Prometheus
Serve the blockchain, storage, and delivery metrics of a running Logos node on one OpenMetrics endpoint and scrape it with Prometheus.
This document is accurate for Testnet v0.3.
This procedure covers adding the openmetrics module to a Logos node and pointing Prometheus at it. openmetrics runs a small HTTP server inside the node. On every scrape, it asks each module you list for its metrics and returns them as one OpenMetrics document, with a module label on every series. It is intended for node operators who want dashboards and alerts for a node they already run.
The steps continue from Run a Logos node with blockchain, storage, and delivery and use the same logos user, paths, and logosctl session.
- A Logos node set up with Run a Logos node with blockchain, storage, and delivery, with the daemon running and the blockchain, storage, and delivery modules started.
logosctlinstalled.- A Prometheus server that can reach the node over TCP, on the same host or on your private network.
What to expect
- You can scrape blockchain, storage, and delivery metrics from a single
/metricsendpoint on the node. - You can see the node as a healthy target in Prometheus and query its series by
modulelabel. - You can keep the endpoint private and bring it back automatically after the node restarts.
Step 1: Install the openmetrics module
Install the module into the running node. As root, open a shell as the logos user, and run every logosctl command in this procedure from it:
runuser -u logos -- env HOME=/var/lib/logos-node bash
-
Install the pinned
openmetricspackage from the module catalogue:logosctl package install openmetrics \--version 0.1.2 \--root-hash 15b22b2020bf83f775b6d55f2e62ceb85582d1720c5d56099b8edd33928a13bb \--yes- The running node picks up the new package without a restart.
-
Load the module:
logosctl module load openmetrics- The output must include
"module":"openmetrics","status":"ok".
- The output must include
Step 2: Turn on the blockchain node's metrics
The blockchain node keeps its metrics off unless its configuration turns them on, and it reads that setting only when the module starts. The user_config.yaml that generate_user_config writes has them off.
-
Turn the metrics on in the node configuration:
sed -i 's/enable_open_metrics: false/enable_open_metrics: true/' /var/lib/logos-node/user_config.yamlgrep enable_open_metrics /var/lib/logos-node/user_config.yaml- The output must show
enable_open_metrics: true. The setting is undertracing.metrics. - If you are setting up a new node, make this change after
generate_user_configand before the firststartcall, and skip the next step.
- The output must show
-
Restart the blockchain module so it reads the new setting:
logosctl module unload blockchain_modulelogosctl module load blockchain_modulelogosctl call blockchain_module start /var/lib/logos-node/user_config.yaml ""- The node keeps its state and resumes from the blocks it already stored.
- The
startcall can returnRPC call failed, orcall to 'blockchain_module.start' timed out after 20000ms, while the node replays its stored blocks. The node still starts. Wait a few minutes, then checklogosctl call blockchain_module get_cryptarchia_info.
-
Check that the node reports metrics:
logosctl call blockchain_module collectOpenMetricsText- The result is an OpenMetrics document with
# TYPElines. An empty result means the metrics are still off or the node is not running.
- The result is an OpenMetrics document with
Step 3: Start the metrics endpoint
Tell openmetrics which port to listen on and which modules to collect from.
-
Create the endpoint configuration:
mkdir -p /var/lib/logos-node/openmetricscd /var/lib/logos-node/openmetricscat > config.json <<'EOF'{"port": 9464,"modules": [{ "name": "blockchain_module", "format": "text" },"storage_module",{ "name": "delivery_module", "format": "text" }]}EOFField Purpose portTCP port of the HTTP server. Pick a free port; 9090is the default port of Prometheus itselfmodulesModules to collect from on each scrape modules[].nameModule name, as shown by logosctl module ls --loadedmodules[].formatdata(the default, also used for a bare name) ortextfor modules that already produce OpenMetrics textstorage_modulereturns structured metrics, so a bare name is enough.blockchain_moduleanddelivery_modulereturn OpenMetrics text and need"format": "text". Listed as a bare name, they contribute no metrics.
-
Start the endpoint:
logosctl call openmetrics start @config.json"result":1means the server is listening."result":0means it did not start; see Troubleshooting.
-
Confirm it is serving:
logosctl call openmetrics getInfo- The result must contain
\"running\":trueand\"port\":9464.
- The result must contain
Step 4: Check the endpoint
-
Check that the server answers:
curl http://127.0.0.1:9464/health- The response is
ok.
- The response is
-
Fetch the metrics:
curl -s http://127.0.0.1:9464/metrics | grep -E 'consensus_tip_height|consensus_peers_connected|libp2p_peers|kad_routing_table_peers|repostore_bytes_used'- Expected result: gauges from all three modules, each tagged with the module that reported it. Your values differ:
# TYPE consensus_peers_connected gaugeconsensus_peers_connected{module="blockchain_module",otel_scope_name="logos-blockchain-node"} 127# TYPE consensus_tip_height gaugeconsensus_tip_height{module="blockchain_module",otel_scope_name="logos-blockchain-node"} 3481# HELP libp2p_peers total connected peers# TYPE libp2p_peers gaugelibp2p_peers{module="delivery_module"} 15.0# HELP logos_storage_kad_routing_table_peers total peers in routing table# TYPE logos_storage_kad_routing_table_peers gaugelogos_storage_kad_routing_table_peers{module="storage_module"} 21.0# HELP logos_storage_repostore_bytes_used storage repostore bytes used# TYPE logos_storage_repostore_bytes_used gaugelogos_storage_repostore_bytes_used{module="storage_module"} 31522926.0- The full document holds a few hundred metric families and ends with
# EOF. Storage metrics start withlogos_storage_and delivery metrics withlogos_delivery_. The delivery module also reports its libp2p, discovery, and mix network metrics. - Blockchain metrics have no common prefix (
consensus_,chainsync_,mempool_,network_,storage_, and others) and no# HELPlines. Filter them bymodule="blockchain_module". - A blockchain series appears once the node has recorded it, so a node that just started reports fewer families.
- A module that is not running, or that fails to answer, is left out of the scrape. The other modules are still reported.
Step 5: Keep the endpoint private
The metrics server listens on all network interfaces, not only on 127.0.0.1. The metrics reveal peer counts, traffic, and storage use, so expose the port only to your Prometheus server.
-
Confirm the listening address:
ss -lntp | grep ':9464'- The output shows
0.0.0.0:9464.
- The output shows
-
Make sure the host firewall does not open port
9464/tcpto the internet. If Prometheus runs on another host, allow only that host. For example, withufw, replace<prometheus-ip>with the address of your Prometheus server:sudo ufw allow from <prometheus-ip> to any port 9464 proto tcp- Run this from an account with
sudoaccess, not from thelogosuser shell.
- Run this from an account with
Step 6: Scrape the node with Prometheus
-
Add a scrape job for the node to your Prometheus configuration (
prometheus.yml). Add it as a new item under the existingscrape_configs:key. A secondscrape_configs:key makes Prometheus reject the file. Replace<node-address>with127.0.0.1if Prometheus runs on the node, or with the node's private address otherwise: -
Reload or restart Prometheus so it reads the new job.
-
Check that Prometheus scrapes the node. In the Prometheus UI, open Status > Target health, or query the API from the Prometheus host (default port
9090):curl -s --get http://127.0.0.1:9090/api/v1/query --data-urlencode 'query=up{job="logos-node"}'- The
logos-nodetarget is up, and the query returns the value"1".
- The
-
Query the node's series, for example the number of series each module reports:
count by (module) ({job="logos-node"})- The result lists
blockchain_module,storage_module, anddelivery_module. A few series without amodulelabel, such asup, are added by Prometheus itself.
- The result lists
Step 7: Start the endpoint with the node
The endpoint does not persist across restarts: when the node daemon restarts, the openmetrics module is unloaded and the server stops.
-
If you run the node with the systemd service, add these commands to the module bootstrap script, after the blockchain, storage, and delivery modules start:
logosctl module load openmetricslogosctl call openmetrics start @/var/lib/logos-node/openmetrics/config.json- Collection only reports modules that are running, so start
openmetricsafter the modules it scrapes. - The blockchain setting from Step 2 is stored in
user_config.yaml, so the blockchain module keeps reporting metrics after a restart.
- Collection only reports modules that are running, so start
-
To stop the endpoint without stopping the node, run:
logosctl call openmetrics stop
Troubleshooting
logosctl call openmetrics start returns "result":0
The server did not start. The usual causes are:
- The server is already running. Check with
logosctl call openmetrics getInfo, and runlogosctl call openmetrics stopbefore starting it with a new configuration. - Another process holds the port. Check with
ss -lntp | grep ':9464', then pick a freeportinconfig.json. config.jsonis not valid JSON, orportis missing or not between1and65535.
A module's metrics are missing from /metrics
- Check that the module is loaded and started with
logosctl module ls --loadedand the module's own status call, for examplelogosctl call storage_module isRunning. - Check that
blockchain_moduleanddelivery_moduleare listed with"format": "text". As bare names they contribute no metrics. - If
blockchain_modulereports nothing, runlogosctl call blockchain_module collectOpenMetricsText. An empty result meansenable_open_metricsis nottrueinuser_config.yaml, the module was not restarted after the change, or the node is not running. Repeat Step 2.