For AI agents: a documentation index is available at /llms.txt. Markdown versions of pages are available by appending .md to any documentation URL.
Skip to main content

Profile Besu with Pyroscope

Grafana Pyroscope continuously profiles a running node and shows which code paths consume CPU, memory, and lock time. Use Pyroscope when metrics tell you a node is under load but not which part of Besu is responsible.

The Besu Docker image bundles the Pyroscope Java agent and a default agent configuration file. The agent is inactive until you attach it.

note

The Docker image bundles the agent from Besu 25.6.0 onwards. The binary distribution doesn't include it, so use Java Flight Recorder to profile a node installed from the binary distribution.

Prerequisites

Enable the agent

Attach the bundled agent using BESU_OPTS, and set PYROSCOPE_SERVER_ADDRESS to the address of your Pyroscope server:

docker run -p 8545:8545 -p 30303:30303 \
-e BESU_OPTS=-javaagent:/opt/besu/pyroscope/pyroscope.jar \
-e PYROSCOPE_SERVER_ADDRESS=http://<PYROSCOPE_HOST>:4040 \
-e PYROSCOPE_APPLICATION_NAME=<NODE_NAME> \
hyperledger/besu:latest --network=sepolia

PYROSCOPE_APPLICATION_NAME is the name the node appears under in Grafana. Set a distinct value for each node so you can tell profiles apart.

tip

If you run Pyroscope in the same Docker network under the hostname pyroscope, on the default port 4040, you can omit PYROSCOPE_SERVER_ADDRESS. That address is already the default in the bundled configuration.

View profiles in Grafana

Select the Pyroscope data source in Grafana, then select your node under Service and a profile type such as process_cpu:cpu. The flame graph shows the call stacks that consumed the most CPU over the selected time range, and the table lists the same data by symbol.

Grafana flame graph of Besu CPU profile data from Pyroscope

The root frame sits at the top of the flame graph, and each row below it shows the functions that frame called. A bar's width is the proportion of samples in which that function was on the stack, so wide bars deep in the graph are the hotspots worth investigating.

Change the agent configuration

The image sets PYROSCOPE_CONFIGURATION_FILE to /etc/besu/pyroscope.properties, which contains the following defaults:

PropertyEnvironment variableDefault
pyroscope.server.addressPYROSCOPE_SERVER_ADDRESShttp://pyroscope:4040
pyroscope.application.namePYROSCOPE_APPLICATION_NAMEbesu
pyroscope.formatPYROSCOPE_FORMATjfr
pyroscope.profiling.eventPYROSCOPE_PROFILING_EVENTitimer
pyroscope.profiling.intervalPYROSCOPE_PROFILING_INTERVAL10ms
pyroscope.profiling.allocPYROSCOPE_PROFILING_ALLOC512k
pyroscope.profiling.lockPYROSCOPE_PROFILING_LOCK10ms
pyroscope.upload.intervalPYROSCOPE_UPLOAD_INTERVAL15s
pyroscope.log.levelPYROSCOPE_LOG_LEVELdebug

Override any property with the matching environment variable, which is the property name in uppercase with underscores instead of dots. For example, pyroscope.upload.interval becomes PYROSCOPE_UPLOAD_INTERVAL.

The bundled configuration sets the agent log level to debug. Set PYROSCOPE_LOG_LEVEL=info to reduce how much the agent logs.

To replace the configuration wholesale, mount your own properties file over /etc/besu/pyroscope.properties, or point PYROSCOPE_CONFIGURATION_FILE at a different path. Don't use quotes in the properties file.

For the full set of agent options, including authentication for hosted Pyroscope, see the Pyroscope Java SDK documentation.