Node monitoring and logging

By default, the node log files are stored to the logs subdirectory of the working directory and are rotated. Logging can be printed to the console by passing the --log-to-console command line flag. The default logging level is INFO which can be adjusted by the --logging-level command line argument. This configuration option will affect all modules. Hibernate (the JPA provider used by Corda) specific log messages of level WARN and above will be logged to the diagnostic log file, which is stored in the same location as other log files (logs subdirectory by default). This is because Hibernate may log messages at WARN and ERROR that are handled internally by Corda and do not need operator attention. If they do, they will be logged by Corda itself in the main node log file.

It may be the case that you require to amend the log level of a particular subset of modules (e.g., if you’d like to take a closer look at Hibernate activity). So, for more bespoke logging configuration, the logging settings can be completely overridden with a Log4j2 configuration file assigned to the log4j.configurationFile system property.

The node is using log4j2 asynchronous logging by default (configured via log4j2 properties file in its resources) to ensure that log message flushing is not slowing down the actual processing. If you need to switch to synchronous logging (e.g. for debugging/testing purposes), you can override this behaviour by adding -DLog4jContextSelector=org.apache.logging.log4j.core.selector.ClassLoaderContextSelector to the node’s command line or to the jvmArgs section of the node configuration.

Create a file sql.xml in the current working directory. Add the following text:

<?xml version="1.0" encoding="UTF-8"?>
    <Configuration status="WARN">
            <Console name="Console" target="SYSTEM_OUT">
                <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
            <Logger name="org.hibernate" level="debug" additivity="false">
                <AppenderRef ref="Console"/>
            <Root level="error">
                <AppenderRef ref="Console"/>

Note the addition of a logger named org.hibernate that has set this particular logger level to debug.

Now start the node as usual but with the additional parameter log4j.configurationFile set to the filename as above, for example:

java <Your existing startup options here> -Dlog4j.configurationFile=sql.xml -jar corda.jar

To determine the name of the logger, for Corda objects, use the fully qualified name (e.g., to look at node output in more detail, use net.corda.node.internal.Node although be aware that as we have marked this class internal we reserve the right to move and rename it as it’s not part of the public API as yet). For other libraries, refer to their logging name construction. If you can’t find what you need to refer to, use the --logging-level option as above and then determine the logging module name from the console output.

Node can be configured to run SSH server.

When running a node backed with a H2 database, the node can be configured to expose the database over a socket (see database access when running H2).

Note that in a production set up, it is highly recommended to use an enterprise grade database, and access to the database should be via the usual database tools mechanisms, including access control and restrictions.

This section covers monitoring performance and health of a node in Corda Enterprise with Jolokia and Graphite. General best practices for monitoring (e.g. setting up TCP checks for the ports the node communicates on, database health checks etc.) are not covered here but should be followed.

Like most Java servers, the node can be configured to export various useful metrics and management operations via the industry-standard JMX infrastructure. JMX is a standard API for registering MBeans … objects whose properties and methods are intended for server management. As Java serialization in the node has been restricted for security reasons, the metrics can only be exported via a Jolokia agent.

Jolokia allows you to access the raw data and operations without connecting to the JMX port directly. Nodes can be configured to export the data over HTTP on the /jolokia HTTP endpoint, Jolokia defines the JSON and REST formats for accessing MBeans, and provides client libraries to work with that protocol as well.

Here are a few ways to build dashboards and extract monitoring data for a node:

  • Hawtio is a web based console that connects directly to JVM’s that have been instrumented with a jolokia agent. This tool provides a nice JMX dashboard very similar to the traditional JVisualVM / JConsole MBbeans original.
  • JMX2Graphite is a tool that can be pointed to /monitoring/json and will scrape the statistics found there, then insert them into the Graphite monitoring tool on a regular basis. It runs in Docker and can be started with a single command.
  • JMXTrans is another tool for Graphite, this time, it’s got its own agent (JVM plugin) which reads a custom config file and exports only the named data. It’s more configurable than JMX2Graphite and doesn’t require a separate process, as the JVM will write directly to Graphite.
  • Cloud metrics services like New Relic also understand JMX, typically, by providing their own agent that uploads the data to their service on a regular schedule.
  • Telegraf is a tool to collect, process, aggregate, and write metrics. It can bridge any data input to any output using their plugin system, for example, Telegraf can be configured to collect data from Jolokia and write to DataDog web api.

In order to ensure that a Jolokia agent is instrumented with the JVM run-time, you can choose one of these options:

  • Specify the Node configuration parameter jmxMonitoringHttpPort which will attempt to load the Jolokia driver.
  • Start the node with java -Dcapsule.jvm.args="-javaagent:path/to/jolokia-jvm-{VERSION}-agent.jar=port=7777,host=localhost" -jar corda.jar where path/to/jolokia-jvm-{VERSION}-agent.jar is the path to the driver, and {VERSION} is the version required by Corda, currently 1.6.1.

The following JMX statistics are exported:

  • Corda specific metrics: see Node metrics for a list.
  • Apache Artemis metrics: queue information for P2P and RPC services.
  • JVM statistics: classloading, garbage collection, memory, runtime, threading, operating system.

When using Jolokia monitoring in production, R3 recommends to use a Jolokia agent that reads the metrics from the node and pushes them to the metrics storage, rather than exposing a port on the production machine/process to the internet.

Also ensure to have restrictive Jolokia access policy in place for access to production nodes. The Jolokia access is controlled via a file called jolokia-access.xml. Several Jolokia policy based security configuration files (jolokia-access.xml) are available for dev, test, and prod environments under /config/<env>.

When running in dev mode, Hibernate statistics are also available via the Jolkia interface. These are disabled otherwise due to expensive run-time costs. They can be turned on and off explicitly regardless of dev mode via the exportHibernateJMXStatistics flag on the database configuration.

When starting Corda nodes using Cordformation runner (see running nodes locally), you should see a startup message similar to the following: Jolokia: Agent started with URL

When starting Corda nodes using the ‘driver DSL’, you should see a startup message in the logs similar to the following: Starting out-of-process Node USA Bank Corp, debug port is not enabled, jolokia monitoring port is 7005 {}

The following diagram illustrates Corda flow metrics visualized using hawtio:

hawtio jmx

Corda nodes alternatively support publishing metrics collected via the Codahale metrics library directly to a graphite server. This needs to be configured in the node configuration file:

graphiteOptions = {
  prefix = "<node specific prefix>"
  server = <host name of the graphite server>
  port = <write port on the graphite server>
  sampleIntervalSeconds = 60

The prefix should clearly indicate the node where the metrics are coming from, as this will be the top level discrimator in the graphite metric hierarchy. The graphite server must be running with python pickle transport enabled. Please refer to the documentation on on how to install and run a graphite server.

See Monitoring scenarios for a description of some common node monitoring scenarios when using node metrics.

All garbage collected programs can run faster if you give them more memory, as they need to collect less frequently. As a default JVM will happily consume all the memory on your system if you let it, Corda is configured with a 512mb Java heap by default. When other overheads are added, this yields a total memory usage of about 800mb for a node (the overheads come from things like compiled code, metadata, off-heap buffers, thread stacks, etc).

If you want to make your node go faster and profiling suggests excessive GC overhead is the cause, or if your node is running out of memory, you can give it more by running the node like this:

java -Dcapsule.jvm.args="-Xmx1024m" -jar corda.jar

The example command above would give a 1 gigabyte Java heap.

A frequent requirement is that configuration files must not expose passwords to unauthorised readers. By leveraging environment variables, it is possible to hide passwords and other similar fields.

Take a simple node config that wishes to protect the node cryptographic stores:

myLegalName = "O=PasswordProtectedNode,OU=corda,L=London,C=GB"
keyStorePassword = ${KEY_PASS}
trustStorePassword = ${TRUST_PASS}
p2pAddress = "localhost:12345"
devMode = false
networkServices {
    doormanURL = ""
    networkMapURL = ""

By delegating to a password store, and using command substitution it is possible to ensure that sensitive passwords never appear in plain text. The below examples are of loading Corda with the KEY_PASS and TRUST_PASS variables read from a program named corporatePasswordStore.

KEY_PASS=$(corporatePasswordStore --cordaKeyStorePassword) TRUST_PASS=$(corporatePasswordStore --cordaTrustStorePassword) java -jar corda.jar
$env:KEY_PASS=$(corporatePasswordStore --cordaKeyStorePassword); $env:TRUST_PASS=$(corporatePasswordStore --cordaTrustStorePassword); java -jar corda.jar

For launching on Windows without PowerShell, it is not possible to perform command substitution, and so the variables must be specified manually, for example:

SET KEY_PASS=mypassword & SET TRUST_PASS=mypassword & java -jar corda.jar

Instead of hiding sensitive data using environment variables, another option is to use configuration obfuscation. Corda ships with a configuration obfuscator which allows the user to censor string properties in the configuration file. The config would look something like this:

keyStorePassword = "<{Kwby0G9c/+jxJM+c7Vaiow==:pdy+UaakdFSmmh8WWuBOoQ==}>"
trustStorePassword = "<{Kwby0G9c/+jxJM+c7Vaiow==:pdy+UaakdFSmmh8WWuBOoQ==}>"
p2pAddress = "localhost:12345"
devMode = false

The values for keyStorePassword and trustStorePassword in the above example are encrypted, using a key that is tied to the hosting machine’s primary hardware address. The implications of this is that:

  • The configuration file is rendered unusable on other machines without manually decrypting obfuscated fields beforehand (since the hardware address would be different).
  • Sensitive data is unreadable without additional processing.
  • It becomes harder for adversaries to trawl for passwords and sensitive data on disk.

Was this page helpful?

Thanks for your feedback!

Chat with us

Chat with us on our #docs channel on slack. You can also join a lot of other slack channels there and have access to 1-on-1 communication with members of the R3 team and the online community.

Propose documentation improvements directly

Help us to improve the docs by contributing directly. It's simple - just fork this repository and raise a PR of your own - R3's Technical Writers will review it and apply the relevant suggestions.

We're sorry this page wasn't helpful. Let us know how we can make it better!

Chat with us

Chat with us on our #docs channel on slack. You can also join a lot of other slack channels there and have access to 1-on-1 communication with members of the R3 team and the online community.

Create an issue

Create a new GitHub issue in this repository - submit technical feedback, draw attention to a potential documentation bug, or share ideas for improvement and general feedback.

Propose documentation improvements directly

Help us to improve the docs by contributing directly. It's simple - just fork this repository and raise a PR of your own - R3's Technical Writers will review it and apply the relevant suggestions.