You cannot swim for new horizons until you have courage to lose sight of the shore.

—WILLIAM FAULKNER

Chapter 12: Receivers

What is a Receiver?

A receiver is a Logback component that receives logging events from a remote appender and logs each received event according to local policy. Using a combination of socket-based appenders and receivers, it is possible to construct sophisticated topologies for distribution of application logging events over a network.

A receiver extends the ch.qos.logback.classic.​net.ReceiverBase class. By virtue of the fact that a receiver extends this class, a receiver participates in the Logback component LifeCycle and a receiver is ContextAware.

Historically, support for logging event delivery over a network connection in Logback has been provided by SocketAppender and the corresponding SimpleSocketServer. The appender acts as a client, initiating a network connection to the server application, and delivering logging events via the network connection. The receiver component and corresponding appender support offers much greater flexibility.

A receiver component is configured in logback.xml, just like any other logback component. This allows the full capabilities of Joran to be utilized in configuring a receiver component. Moreover, any application can receive logging events from remote appenders by simply configuring one or more receiver components.

Connection initiation between an appender and a receiver can occur in either direction. A receiver can act in the role of a server, passively listening for connections from remote appender clients. Alternatively, a receiver can act in the client role, initiating a connection to a remote appender which is acting in the server role. Regardless of the respective roles of the appender and receiver, logging events always flow from the appender towards the receiver.

The flexibility to allow a receiver to initiate the connection to an appender is particularly useful in certain situations:

A logback configuration can include any number of receiver components acting in any combination of the server or client roles. The only restrictions are that each receiver acting in the server role must listen on a distinct port, and each receiver acting in the client role will connect to exactly one remote appender.

Receivers that Act in the Server Role

A receiver that is configured to act in the server role passively listens for incoming connections from remote appenders. This is functionally equivalent to using the standalone SimpleSocketServer application, except that by using the receiver component, any application that uses Logback Classic can receive logging events from remote appenders by simply configuring the receiver in logback.xml.

Logback includes two receiver components that act in the server role; ServerSocketReceiver and its SSL-enabled subtype SSLServerSocketReceiver. Both of these receiver components are designed to accept connections from incoming SocketAppender (or SSLSocketAppender) clients.

The ServerSocketReceiver components provide the following configurable properties:

Property Name Type Description
address String The local network interface address on which the receiver will listen. If this property is not specified, the receiver will listen on all network interfaces.
port int The TCP port on which the receiver will listen. If this property is not specified, a default value will be used.
ssl SSLConfiguration Supported only for SSLServerSocketReceiver, this property provides the SSL configuration that will be used by the receiver, as described in Using SSL.

Using ServerSocketReceiver

The following configuration uses the ServerSocketReceiver component with a minimal local appender and logger configuration. Logging events received from a remote appender will be matched by the root logger and delivered to the local console appender.

Example: Basic ServerSocketReceiver Configuration (logback-examples/​src/main/resources/​chapters/receivers/​socket/receiver1.​xml)

<configuration debug="true">

  <appender name="CONSOLE" class="ch.qos.logback.​core.ConsoleAppender">
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="CONSOLE" />
  </root>

  <receiver class="ch.qos.logback.​classic.net.server.​ServerSocketReceiver">
    <port>${port}</port>
  </receiver>

</configuration>

Requires a server call. Please wait a few seconds.

Note that the receiver component's class attribute identifies the receiver subtype that we wish to use. In this example we are using ServerSocketReceiver.

Our example server application is very similar in function and design to SimpleSocketServer. It simply accepts a path for a logback configuration file as a command line argument, and runs the given configuration. While our example is somewhat trivial, keep in mind that you can configure logback's ServerSocketReceiver (or SSLServerSocketReceiver) component in any application.

From a shell in the logback-examples directory, we can run our example server application as follows:

java -Dport=6000 chapters.receivers.socket.ReceiverExample \ src/main/java/chapters/​receivers/socket/​receiver1.xml

We can connect to the running receiver using a client application that is configured with a SocketAppender. Our example client application simply loads a logback configuration that will connect a socket appender to our example receiver. It then awaits input from the user in the form of a message that will be relayed to the receiver. We can run the example client application as follows:

java -Dhost=localhost -Dport=6000 \ chapters.receivers.socket.AppenderExample \ src/main/java/chapters/​receivers/socket/​appender1.xml

Using SSLServerSocketReceiver

The following configuration repeats the same minimal appender and logger configuration, but uses the SSL-enabled receiver component that acts in the server role.

Example: Basic SSLServerSocketReceiver Configuration (logback-examples/​src/main/resources/​chapters/receivers/​socket/receiver2.​xml)

<configuration debug="true">

  <appender name="CONSOLE" class="ch.qos.logback.​core.ConsoleAppender">
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="CONSOLE" />
  </root>

  <receiver class="ch.qos.logback.​classic.net.server.​SSLServerSocketReceiver">
    <port>${port}</port>
    <ssl>
      <keyStore>
        <location>${keystore}</location>
        <password>${password}</password>
      </keyStore>
    </ssl>
  </receiver>

</configuration>

Requires a server call. Please wait a few seconds.

The essential differences between this configuration and the previous example using ServerSocketReceiver are the specification of SSLServerSocketReceiver in the class attribute and the presence of the nested ssl property, which is used here to specify the location and password for the key store containing the receiver's private key and certificate, using substitution variables. See Using SSL for details on configuring SSL properties for Logback components.

We can run this configuration using the same example server configuration, with just a couple of additional configuration properties:

java -Dport=6001 \ -Dkeystore=file:src/​main/java/chapters/​appenders/socket/​ssl/keystore.jks \ -Dpassword=changeit \ chapters.receivers.​socket.ReceiverExample \ src/main/java/chapters/​receivers/socket/​receiver2.xml

Note that the keystore property given on the command line specifies a file URL that identifies the location of the key store. You may also use a classpath URL as described in Using SSL.

We can connect to the running receiver using a client application that is configured with a SSLSocketAppender. We use the sample example client application used in the previous example, with a configuration file that uses an SSL-enabled appender. We run the example as follows:

java -Dhost=localhost -Dport=6001 \ -Dtruststore=file:src/​main/java/chapters/​appenders/socket/​ssl/truststore.​jks \ -Dpassword=changeit \ chapters.receivers.​socket.AppenderExample \ src/main/java/chapters/​receivers/socket/​appender2.xml

Note that our example is using a self-signed X.509 credential that is suitable for testing and experimentation, only. In a production setting, you should obtain an appropriate X.509 credential to identify your SSL-enabled logback components. See Using SSL for more information.

Receivers that Act in the Client Role

A receiver that is configured to act in the client role initiates a connection to a remote appender. The remote appender must be a server type, such as ServerSocketAppender.

Logback includes two receiver components that act in the client role; SocketReceiver and its SSL-enabled subtype SSLSocketReceiver. Both of these receiver components are designed to initiate a connection to a remote appender that is a ServerSocketAppender (or SSLServerSocketAppender).

The following configuration properties are supported by SocketReceiver subtypes:

Property Name Type Description
remoteHost String The hostname or address of the remote server socket appender.
port int The port number of the remote server socket appender.
reconnectionDelay int A positive integer representing the number of milliseconds to wait before attempting to reconnect after a connection failure. The default value is 30000 (30 seconds).
ssl SSLConfiguration Supported only for SSLSocketReceiver, this property provides the SSL configuration that will be used for this receiver, as described in Using SSL.

Using SocketReceiver

The configuration used for SocketReceiver is quite similar to the previous example that used ServerSocketReceiver. The differences relate to the fact that the roles of client and server are reversed; a receiver of type SocketReceiver is a client, and the remote appender acts as a server.

Example: Basic SocketReceiver Configuration (logback-examples/​src/main/resources/​chapters/receivers/​socket/receiver3.​xml)

<configuration debug="true">
    
  <appender name="CONSOLE" class="ch.qos.logback.​core.ConsoleAppender">    
    <encoder>
      <pattern>%date %-5level [%thread] %logger - %message%n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="CONSOLE" />
  </root>  

  <receiver class="ch.qos.logback.​classic.net.SocketReceiver">
    <remoteHost>${host}</remoteHost>
    <port>${port}</port>
    <reconnectionDelay>10000</reconnectionDelay>
  </receiver>

</configuration>

Requires a server call. Please wait a few seconds.

This configuration will cause logback to connect to a ServerSocketAppender running on the host and port specified by the host and port substitution variables. Logging events received from the remote appender will be logged locally (according to the configuration shown here) via a console appender.

Assuming you are in the logback-examples/ directory, you can run this example configuration using the following command:

The example loads the configuration and then simply waits for logging events from the remote appender. If you run this example when the remote appender is not running, you'll see connection refused messages appearing in the log output, periodically. The receiver will periodically attempt to reconnect to the remote appender until it succeeds or until the logger context is shut down. The delay interval between attempts is configurable using the reconnectionDelay property as shown in the example configuration.

java -Dhost=localhost -Dport=6000 \ chapters.receivers.​socket.ReceiverExample \ src/main/java/chapters/​receivers/socket/​receiver3.xml

We can provide a remote appender to which our example receiver can connect, using the same appender example used previously. The example loads a logback configuration containing a ServerSocketAppender, and then waits input from the user consisting of a message that will be delivered to connected receivers. We can run the example appender application as follows:

java -Dport=6000 \ chapters.receivers.​socket.AppenderExample \ src/main/java/chapters/​receivers/socket/​appender3.xml

If you enter a message to send when the receiver is not connected, note that the message is simply discarded.

Using SocketSSLReceiver

The configuration needed for SSLSocketReceiver is very similar to that used with SocketReceiver. The essential differences are in the class specified for the receiver and the ability to nest the ssl property to specify SSL configuration properties. The following example illustrates a basic configuration:

Example: Basic SSLSocketReceiver Configuration (logback-examples/​src/main/resources/​chapters/receivers/​socket/receiver4.​xml)

<configuration debug="true">

  <appender name="CONSOLE" class="ch.qos.logback.​core.ConsoleAppender">    
    <encoder>
      <pattern>%date %-5level [%thread] %logger - %message%n</pattern>
    </encoder>         
  </appender>

  <root level="DEBUG">
    <appender-ref ref="CONSOLE" />
  </root>  
 
  <receiver class="ch.qos.logback.​classic.net.SSLSocketReceiver">
    <remoteHost>${host}</remoteHost>
    <port>${port}</port>
    <reconnectionDelay>10000</reconnectionDelay>
    <ssl>
      <trustStore>
        <location>${truststore}</location>
        <password>${password}</password>
      </trustStore>
    </ssl>
  </receiver>

</configuration>

Requires a server call. Please wait a few seconds.

Note that the class attribute now specifies SSLSocketReceiver and that in addition to the configuration properties shown in the previous example, this configuration contains an SSL configuration specifying the location and password for a trust store that will be used in validating that the remote appender is trusted. See Using SSL for more information on configuring SSL properties.

You can run this example configuration using the following command:

java -Dhost=localhost -Dport=6001 \ -Dtruststore=file:src/​main/java/chapters/​appenders/socket/​ssl/truststore.​jks \ -Dpassword=changeit \ chapters.receivers.​socket.ReceiverExample \ src/main/java/chapters/​receivers/socket/​receiver4.xml

Once started, the receiver attempts to connect to the specified remote appender. Assuming that the appender is not yet running, you will see a "connection refused" message appearing in the log output periodically; the receiver will periodically retry the connection to the remote appender after delaying for the period of time specified by the reconnectionDelay property.

We can provide a remote appender to which our example receiver can connect, using the same appender example used previously. The example loads a logback configuration containing a SSLServerSocketAppender, and then awaits input from the user consisting of a message that will be delivered to connected receivers. We can run the example appender application as follows:

java -Dport=6001 \ -Dkeystore=file:src/​main/java/chapters/​appenders/socket/​ssl/keystore.jks \ -Dpassword=changeit \ chapters.receivers.​socket.AppenderExample \ src/main/java/chapters/​receivers/socket/​appender4.xml

If you enter a message to send when the receiver is not connected, note that the message is simply discarded.

It is important to note once again that our example is using a self-signed X.509 credential that is suitable for testing and experimentation, only. In a production setting, you should obtain an appropriate X.509 credential to identify your SSL-enabled logback components. See Using SSL for more information.