metrics
Exposes Prometheus-compatible metrics for monitoring node performance and health.
Method: GET /metrics
Parameters: None
Returns: Prometheus-format text response with all collected metrics
Example Request:
curl -X GET http://localhost:9153/metricsExample Response:
# HELP genlayer_node_cpu_usage_percent Current CPU usage percentage (0-100)
# TYPE genlayer_node_cpu_usage_percent gauge
genlayer_node_cpu_usage_percent{component="node"} 15.5
genlayer_node_cpu_usage_percent{component="genvm-llm"} 45.2
genlayer_node_cpu_usage_percent{component="genvm-web"} 12.8
genlayer_node_cpu_usage_percent{component="webdriver"} 5.3
# HELP genlayer_node_memory_rss_bytes Resident Set Size (RSS) memory usage in bytes
# TYPE genlayer_node_memory_rss_bytes gauge
genlayer_node_memory_rss_bytes{component="node"} 524288000
genlayer_node_memory_rss_bytes{component="genvm-llm"} 2147483648
# HELP genlayer_node_network_rx_bytes_total Total bytes received across all network interfaces
# TYPE genlayer_node_network_rx_bytes_total counter
genlayer_node_network_rx_bytes_total{component="node"} 1073741824Available Metrics
The node collects metrics for three main components:
- Node - The main node process
- GenVM - The GenVM modules (LLM and Web)
- WebDriver - The WebDriver container
Operator Condition Metrics
genlayer_node_operator_condition_state{condition,state}: one-hot gauge for the current catalog state. All state series are prewarmed at process start.genlayer_node_operator_condition_occurrences_total{condition,reason}: accepted failed observations by stable reason.genlayer_node_operator_condition_transitions_total{condition,from,to}: lifecycle transitions, including recovery.genlayer_node_operator_condition_last_success_timestamp_seconds{condition}: Unix timestamp of the last successful observation, or zero before one occurs.
condition, state, reason, from, and to come from the fixed startup catalog; upstream error text is never used as a label.
occurrences_total counts differently per condition kind, so the counter stays comparable: an observed condition (folded from duty traffic) counts every failed observation, while a polled condition counts only entry into a failing state. Counting every failed poll would scale the counter with the poll interval rather than the fault — a three-day ban at a ten-second poll would read as roughly 26,000 events.
CPU Metrics
genlayer_node_cpu_usage_percent
Current CPU usage percentage (0-100).
Type: Gauge
Labels:
component: One ofnode,genvm-llm,genvm-web,webdriver
Example:
genlayer_node_cpu_usage_percent{component="node"} 15.5
genlayer_node_cpu_usage_percent{component="genvm-llm"} 45.2
genlayer_node_cpu_usage_percent{component="genvm-web"} 12.8
genlayer_node_cpu_usage_percent{component="webdriver"} 5.3Memory Metrics
genlayer_node_memory_rss_bytes
Resident Set Size (RSS) memory usage in bytes.
Type: Gauge
Labels:
component: One ofnode,genvm-llm,genvm-web,webdriver
Example:
genlayer_node_memory_rss_bytes{component="node"} 524288000
genlayer_node_memory_rss_bytes{component="genvm-llm"} 2147483648genlayer_node_memory_vms_bytes
Virtual Memory Size (VMS) in bytes.
Type: Gauge
Labels:
component: One ofnode,genvm-llm,genvm-web,webdriver
Note: Only available for node and GenVM components.
genlayer_node_memory_usage_bytes
Current memory usage in bytes (WebDriver only).
Type: Gauge
Labels:
component:webdriver
genlayer_node_memory_limit_bytes
Memory limit in bytes (WebDriver only).
Type: Gauge
Labels:
component:webdriver
genlayer_node_memory_percent
Memory usage percentage.
Type: Gauge
Labels:
component: One ofgenvm-llm,genvm-web,node,webdrivernode: Node address (hex format)
genlayer_node_memory_peak_bytes
Peak memory usage in bytes (GenVM components only).
Type: Gauge
Labels:
component: One ofgenvm-llm,genvm-webnode: Node address (hex format)
Network Metrics
genlayer_node_network_rx_bytes_total
Total bytes received across all network interfaces.
Type: Counter
Labels:
component: One ofnode,genvm-llm,genvm-web,webdrivernode: Node address (hex format)
Example:
genlayer_node_network_rx_bytes_total{component="node",node="0x84b6cbd007511352d3fea26834c5c39a440903c4"} 96879942
genlayer_node_network_rx_bytes_total{component="webdriver",node="0x84b6cbd007511352d3fea26834c5c39a440903c4"} 84genlayer_node_network_tx_bytes_total
Total bytes transmitted across all network interfaces.
Type: Counter
Labels:
component: One ofnode,genvm-llm,genvm-web,webdrivernode: Node address (hex format)
Disk Metrics
genlayer_node_disk_free_bytes
Available free disk space in bytes.
Type: Gauge
Labels:
component:nodedirectory: One ofgenlayer.db,keystore,logsnode: Node address (hex format)
genlayer_node_disk_total_bytes
Total disk space in bytes.
Type: Gauge
Labels:
component:nodedirectory: One ofgenlayer.db,keystore,logsnode: Node address (hex format)
genlayer_node_disk_usage_bytes
Used disk space in bytes.
Type: Gauge
Labels:
component:nodedirectory: One ofgenlayer.db,keystore,logsnode: Node address (hex format)
genlayer_node_disk_usage_percent
Used disk space as percentage.
Type: Gauge
Labels:
component:nodedirectory: One ofgenlayer.db,keystore,logsnode: Node address (hex format)
Node Status Metrics
genlayer_node_blocks_behind
Number of blocks behind the latest block.
Type: Gauge
Labels:
node: Node address (hex format)
genlayer_node_latest_block
Latest block number in the network.
Type: Gauge
Labels:
node: Node address (hex format)
genlayer_node_processing_block
Currently processing block number.
Type: Gauge
Labels:
node: Node address (hex format)
genlayer_node_synced_block
Last synced block number.
Type: Gauge
Labels:
node: Node address (hex format)
genlayer_node_synced
Node synchronization status (1 = synced, 0 = not synced).
Type: Gauge
Labels:
node: Node address (hex format)
genlayer_node_prime_blocked_insufficient_funds
Whether a mandatory validator prime is currently blocked by an unfunded operator wallet (1 = blocked, 0 = not blocked). While blocked the validator cannot pay for consensus duty transactions and is flagged idle each round — fund the operator wallet to recover.
Type: Gauge
Labels:
node: Node address (hex format)
genlayer_node_uptime_seconds
Node uptime in seconds.
Type: Gauge
Labels:
component:nodenode: Node address (hex format)
Transaction Metrics
genlayer_node_transactions_accepted_synced_total
Total number of accepted and synced transactions.
Type: Gauge
Labels:
node: Node address (hex format)
genlayer_node_transactions_activated_total
Total number of activated transactions.
Type: Gauge
Labels:
node: Node address (hex format)
genlayer_node_transactions_leader_proposed_total
Total number of transactions proposed as leader.
Type: Gauge
Labels:
node: Node address (hex format)
genlayer_node_transactions_leader_revealed_total
Total number of transactions revealed as leader.
Type: Gauge
Labels:
node: Node address (hex format)
genlayer_node_transactions_validator_commit_total
Total number of validator commit votes.
Type: Gauge
Labels:
node: Node address (hex format)
genlayer_node_transactions_validator_reveal_total
Total number of validator reveal votes.
Type: Gauge
Labels:
node: Node address (hex format)
Gas Metrics (duty transactions)
Emitted inline from the shared consensus gas estimator and transactor, so they cover every duty method (finalizeTransaction, commitVote, revealVote, proposeReceiptWithFees, topUpAndSubmitAppeal, activateTransaction, validatorPrime, epochAdvance, ...). All are true counters.
genlayer_node_gas_estimation_total
Outcome of every duty gas estimation.
Type: Counter
Labels:
method: Contract method nameoutcome: One ofsuccess(real RPC estimate),fallback_block_limit(estimation failed; submitted at full block gas limit),fallback_cache/fallback_cache_scaled(estimation failed; reused gas from the shared calldata-length-keyed cache, possibly learned from a different method)
genlayer_node_gas_estimation_capped_total
Estimation succeeded but the safety-multiplied estimate (or per-call reserve) exceeded the block gas limit and was silently capped — the safety margin is gone while everything still works.
Type: Counter
Labels:
method: Contract method name
genlayer_node_gas_shortfall_total
Confirmed on-chain out-of-gas: the transaction landed but ran out of gas mid-execution. Self-heals — the node retries with a larger gas limit — so a single occurrence is not actionable; a sustained rate signals systematic under-estimation (treat as a warning, not a page).
Type: Counter
Labels:
method: Contract method namereason: One oftyped_shortfall(InsufficientGasForInternalMessageCreationrevert with exact gas requirement),out_of_gas(explicitOutOfGasrevert),heuristic(undecoded revert that consumed gas above the exhaustion threshold)
genlayer_node_gas_block_limit_exhausted_total
Gas shortfall while the gas limit was already capped at the block limit: the work cannot fit in one block and retrying cannot help. Non-self-healing — any occurrence is actionable (page-worthy).
Type: Counter
Labels:
method: Contract method name
genlayer_node_gas_spent_wei_total
Cumulative wei actually billed for gas, from each mined duty receipt (gasUsed × effectiveGasPrice). Reverted attempts are billed too and are accounted per attempt; submissions that never land cost nothing. The reverted slice is the exact cost of failed work, and sum(genlayer_node_gas_spent_wei_total) is the operator's total billed duty gas.
Type: Counter
Labels:
method: Contract method nameoutcome: One ofsuccess,revertedprice_source:effective(receipt's billed price) orfee_cap(submitted fee cap used as an upper bound when the RPC omitseffectiveGasPrice)
Consensus Submission Metrics
genlayer_node_consensus_submit_total
Terminal outcome of every duty submission.
Type: Counter
Labels:
method: Contract method nameoutcome: One ofsuccess(landed and executed),reverted(landed, contract rejected — gas still billed),failed(never landed: RPC/nonce/funds/authorization)
genlayer_node_consensus_revert_total
Decoded revert causes, one increment per observed revert (attempt-level).
Type: Counter
Labels:
method: Contract method nameerror: Decoded custom error from the fee/gas allowlist (InsufficientFeesForRound,InsufficientFees,FailedFeeTransfer,FeeSettlementNotCompleted,MaxPriceExceeded,ExecutionBudgetExceeded,MessageBudgetExceeded,BudgetTooLow,RollupBudgetBelowFloor,InsufficientBondCustody,InvalidAppealBond,AppealBondTooLow,InsufficientGasForInternalMessageCreation,OutOfGas); anything else collapses toother
Fee Flow Metrics (v0.6 ConsensusMainWithFees)
Note: there are no dedicated appeal-bond metrics. No node runtime path submits appeals — appellants are external clients funding bonds from their own wallets. If a validator appeal duty ever ships, the method-labeled gas/submission metrics above cover it under method="topUpAndSubmitAppeal" with no code change.
genlayer_node_fees_operator_insufficient_funds_total
Duty submissions rejected because the operator account cannot cover value + gas. Complements the genlayer_node_prime_blocked_insufficient_funds gauge by leaving a trace of dips that recover between scrapes. A sustained increase means the operator wallet needs funding (page-worthy).
Type: Counter
genlayer_node_fees_settlement_events_total
Fee-settlement events decoded from this node's own mined finalize receipts. Finalize runs under a staggered lease, so each finalize is observed by exactly one node — aggregate fleet-wide with sum by (network). Use the severity label to alert on failures without enumerating event names: genlayer_node_fees_settlement_events_total{severity="alarm"} covers all three failure modes and any future one.
Type: Counter
Labels:
event: One ofUnifiedFeesDistributed(fees distributed at settlement),FeesRefunded(surplus returned to the sender),FeeSettlementFailed(finalize succeeded but settlement failed — validators unpaid untilretryFeeSettlement),CommitFinalFeesFailed(tx finalized without fee settlement),ValueWithdrawalFailed(a best-effort transfer — refund/appealer payout — failed; funds stay custodied pending recovery)severity:alarmfor the three failure events (unpaid or stuck-funds modes needing operator action) orinfofor the normalUnifiedFeesDistributed/FeesRefundedhappy path
genlayer_node_fees_distributed_wei_total
Total wei moved at fee settlement across all recipients — committee payouts plus sender/contributor refunds plus appealer rewards — summed from UnifiedFeesDistributed amounts in this node's finalize receipts. It excludes amounts retained in staking custody (amountToStaking). This is a network "value settled" liveness signal, not per-node earnings — for a validator's own income use genlayer_node_fees_earned_wei_total.
Type: Counter
genlayer_node_fees_earned_wei_total
This node's validator earnings credited at prime, read from the ValidatorPrime event when a prime is effective. This is the accurate per-node income (unlike fees_distributed_wei_total, which is whole-committee plus refunds). Earnings settle into stake per epoch, so this series lags settlement by up to one prime interval. Pair type="fee_rewards" with genlayer_node_gas_spent_wei_total for operator net P&L (earned − gas_spent).
Type: Counter
Labels:
type: One offee_rewards(fee-flow income),validator_rewards,delegator_rewards(staking-reward components)
genlayer_node_fees_penalties_wei_total
This node's fee penalties deducted at prime, read from the same ValidatorPrime event. Kept separate from fees_earned_wei_total so earnings stay gross income; subtract this for net.
Type: Counter
genlayer_node_external_message_delivery_total
External messages this node's own delivery calls (flushExternalMessages, flushInternalMessages, finalizeTransaction) resolved or paused, read from their mined receipts. A paused message was not called and not charged; the node retries it with a backoff (30 s doubling to 10 min) until the chain reports it issued. A paused_* series that keeps rising for one network means a message nobody can deliver.
Type: Counter
Labels:
outcome:delivered(ran and succeeded),call_failed(ran and failed; final),paused_gas(no room to forward its gas envelope),paused_value(its value was not yet available),cancelled_unfunded(its open-bucket envelope was never funded; value refunded),cancelled_ceiling(its gas limit is above the current ceiling; value refunded)
genlayer_node_external_message_reimbursed_wei_total
Wei the chain reimbursed this node for running external messages: gas used times the transaction's locked gas price. Pair it with gas_spent_wei_total for the net cost of delivery.
Type: Counter
Go Runtime Metrics
The endpoint also exposes standard Go runtime metrics including:
go_gc_duration_seconds- Garbage collection duration summarygo_goroutines- Number of active goroutinesgo_memstats_*- Go memory statistics (heap, stack, GC)go_threads- Number of OS threads
Process Metrics
Standard process metrics are also available:
process_cpu_seconds_total- Total CPU timeprocess_resident_memory_bytes- Resident memory sizeprocess_virtual_memory_bytes- Virtual memory sizeprocess_open_fds- Number of open file descriptorsprocess_network_receive_bytes_total- Network bytes receivedprocess_network_transmit_bytes_total- Network bytes transmitted
Prometheus Handler Metrics
Metrics about the metrics endpoint itself:
promhttp_metric_handler_requests_total- Total scrape requests by status codepromhttp_metric_handler_requests_in_flight- Current scrapes being served
Configuration
Metrics collection can be configured in the node configuration file:
metrics:
interval: "15s" # Default interval for all collectors
collectors:
node:
enabled: true # Enable/disable node metrics
interval: "30s" # Optional: Override default interval
genvm:
enabled: true # Enable/disable GenVM metrics
# Uses default interval (15s)
webdriver:
enabled: true # Enable/disable WebDriver metrics
interval: "60s" # Optional: Override default intervalDefault Values
metrics.interval: 15s (applies to all collectors by default)enabled: true (for each collector)interval: Uses metrics.interval if not specified per collector
Configuration Priority
- Collector-specific
interval(if specified) - Global
metrics.interval(if specified) - System default (15s)
Troubleshooting
No Metrics for GenVM
GenVM processes are ephemeral and only run when executing smart contracts. If you don't see GenVM metrics, it's likely that no contracts are currently being executed.
WebDriver Metrics Missing
Ensure the WebDriver container is running:
docker ps | grep genlayer-node-webdriverIf not running, start it:
task docker:webdriver:docker-compose:up:detachMetrics Not Updating
Check if metrics collection is enabled in your configuration and that the node has been restarted after configuration changes.
Performance Considerations
- Collection intervals can be increased to reduce overhead further
- Each collector runs independently and won't block others if one fails