Asynchronous Monitoring

By default, monitor events are routed to destinations synchronously. This may result in significant performance impact for applications that frequently emit events. The Fabric3 monitor implementation can be configured to route asynchronously using an LMAX Disruptor ring buffer as depicted below:

 

To enable asynchronous monitor event routing, use the mode attribute of the monitor element in systemConfig.xml

<f3:monitor mode="asynchronous">
   <appenders>
      <appender.file file="application.log"/>
   </appenders>
</f3:monitor>

The mode attribute is set to "asynchronous," which indicates routing should be done using a ring buffer. If you plan to use asynchronous monitoring, keep in mind several things. The first is to select a ring buffer size that is large enough to avoid wrapping events (see the LMAX Disruptor documentation for more information). The default value is set at 65536 slots. The second is how buffers for writing monitor event data are handled. To avoid object creation, Fabric3 pre-allocates byte buffers with a configurable but fixed size (3,000 bytes by default) for writing monitor events. If the byte buffer size is not large enough to handle a message, you will need to increase the pre-allocated size or data will be truncated. Setting the ring buffer slot size and byte buffer capacity are done using the ring.size and capacity attributes respectively:  

<f3:monitor name="ApplicationDestination" mode="asynchronous" ring.size="65536" capacity="3000">
   ...
</f3:monitor>

If asynchronous monitor routing is configured, it is also recommended to use the Fabric3 bytecode generation extension (Maven coordinates {{org.codehaus.fabric3:fabric3-bytecode-proxy}} for creating monitor proxies. This is done by including the extension in the runtime /extensions directory and setting the proxy attribute to "bytecode" as follows:

<f3:monitor name="ApplicationDestination" mode="asynchronous" ring.size="65536" capacity="3000" proxy="bytecode">
   ...
</f3:monitor>

As a final performance recommendation, you should also consider whether to include formatted timestamp information in the log output. Formatting is a performance drain and can be avoided by using a raw nanosecond timestamp. This can be configured by setting the timestamp attribute to "unformatted" or "none":

<f3:monitor name="ApplicationDestination" mode="asynchronous" ring.size="65536" capacity="3000" proxy="bytecode" timestamp="unformatted">
   ...
</f3:monitor>

The monitor ring buffer can be fine-tuned using the following attributes. For more information, consult the LMAX Disruptor documentation:

  • capacity
  • ring.size
  • wait.strategy
  • blocking.timeout
  • spin.timeout
  • yield.timeout
  • phased.blocking.type