Logging
This page is the operator and developer reference for reading and configuring Block Node logs: the format, how to change the log level (globally, per package, or per single class), and when to reach for logs versus metrics.
For the level definitions engineers apply when writing code, see Logging Guidelines.
For the why (framework, trade-offs, design decisions), see Logging Architecture.
For incident runbooks and the log playbook, see Troubleshooting.
Table of contents
Log format
Logs are single-line text written to stdout/stderr (and, in container deployments, to a rotating file), so they ingest cleanly into Loki, ELK, Splunk, etc.
Production (Docker / Kubernetes) uses
java.util.logging.SimpleFormatter:Fields:
<date> <time.millis><tz> <LEVEL> [<class> <method>] <message>.Local development uses
CleanColorfulFormatter— the same fields, ANSI-coloured by level (ERROR red, WARNING yellow, INFO white, DEBUG/TRACE cyan), with the class shortened to its simple name.
In production the rotating log file is written to /opt/hiero/block-node/logs/blocknode-%g.log (50 MB per file, 15 files retained ≈ 750 MB of history). In Kubernetes this lives on a dedicated logging volume.
Logs vs. metrics: which one do I use?
The Block Node follows the standard split — metrics for progress, logs for problems:
How many / how fast / how healthy over time
Metrics (metrics reference)
block height, blocknode_verification_blocks_failed, receive latency, queue depth
What specific, notable thing happened, and why
Logs
a verification rejection, an I/O failure, a plugin failing to start
Per-block success and throughput are metrics, not per-block INFO logs. Production enables INFO and above, and INFO is deliberately low-volume so that a WARNING or ERROR stands out. To watch block progression continuously at INFO, use the periodic status heartbeat line; for block-by-block detail, enable DEBUG on demand.
Log levels
The code uses System.Logger levels; the log configuration file uses the equivalent java.util.logging (JUL) names:
System.Logger
JUL name (use this in logging.properties)
Enabled in production?
ERROR
SEVERE
yes
WARNING
WARNING
yes
INFO
INFO
yes (default)
DEBUG
FINE
no (enable on demand)
TRACE
FINEST
no
Verbosity order, most to least: ALL FINEST FINER FINE CONFIG INFO WARNING SEVERE OFF. Setting a level enables that level and everything less verbose. Example: FINE shows FINE, INFO, WARNING, SEVERE.
Changing the log level
Levels are controlled entirely through a JUL logging.properties file — there is no LOG_LEVEL environment variable. The three scopes below work identically in every environment; only which file you edit differs.
Per single class
Use the fully-qualified class name plus .level. This is the most surgical control — raise one noisy or interesting class without touching anything else:
Per package
Drop the class name to target a whole package subtree:
Globally
The root .level sets the default for anything without a more specific rule:
More specific rules always win over less specific ones, so you can combine them — e.g. keep .level = INFO globally but set org.hiero.block.node.backfill.level = FINE to debug only backfill.
Local / jar runs
Edit the bundled file and rerun:
Or point the JVM at any file without rebuilding:
Docker
Edit the mounted config file and restart the container:
The container already sets -Djava.util.logging.config.file to that path via JAVA_TOOL_OPTIONS, so the file is picked up on restart.
Kubernetes / Helm
Set the global level and any per-package/class rules in your Helm values; they are rendered into the logging.properties ConfigMap and mounted into the pod:
Apply with helm upgrade … (or kubectl apply the rendered ConfigMap) and restart the StatefulSet pods so the new configuration is loaded.
Enabling DEBUG on demand (log-only troubleshooting)
If you can only see logs (no metrics/Grafana) and need block-by-block detail during an incident, raise just the relevant package to FINE, observe, then revert — rather than enabling DEBUG globally:
Add a targeted rule (pick the subsystem you are investigating):
Restart / reload so the change takes effect, and reproduce the issue.
Revert the rule once done — DEBUG is high-volume and not meant to run continuously in production.
See the troubleshooting playbook for which subsystem to raise for a given symptom, and the healthy-node INFO signature to compare against.
Last updated