This tutorial is an introduction to monitoring the dependency injection container at runtime, we call this auditing.
The reader should be proficient in Java, maven, git, Spring and have completed the second lottery tutorial before
starting this tutorial.
Our goal is to create a custom monitoring class that will observe the event processing without any changes to the
application code, and record the following statistics:
Node stats, method invocation count grouped by bean instance
Event stats, method invocation count grouped by exported method
Node method stats, method invocation count grouped by bean instance and method
At the end of this tutorial you should understand:
The role of the Auditor interface in Fluxtion
How the auditor is notified by the container
How to implement a custom auditor
How to load a custom auditor in the container
Example project
The example project demonstrates the integration of an Auditor.
Auditing concepts
As event driven systems grow more complex tools are needed to monitor critical application metrics giving early
warning of potential problems. It is preferable to develop monitoring separately to application code so that we do not
accidentally introduce bugs to business functionality, and we can add or remove monitoring to the application without
changing functional behaviour.
In Fluxtion we achieve this through the Auditor interface.
Client code implements the Auditor interface and register an auditor instance at build time. At runtime the custom
auditor receives monitoring notifications with event metadata attached. The auditor is free to process the event
metadata in any way it wants.
Processing logic
Our design sketches show how the SystemStatisticsAuditor integrates into our system. An auditor is injected into all
event flow calls within the running event processor. SystemStatisticsAuditor implements and exports the LotterySystemMonitor
service interface.
The Auditor interface is copied below with javadoc comments removed
Methods in the interface are called by the container at runtime except auditInvocations, which is called at build time.
The callback nodeInvoked is a high frequency notification called on every method invoked on every bean,
auditInvocations controls whether this monitoring method is notified at runtime.
Javadoc is attached to the class for detail reading, but it is important to understand these concepts:
init called once before any other lifecycle methods
nodeRegistered called after init before any lifecycle methods, allows the auditor to build a map of beans at startup
eventReceived called when a service call or event is received by the container. Precedes any bean method calls
nodeInvoked called before any bean service or trigger method in an event processing cycle
processingComplete called at the end of a processing cycle
tearDown called once when the container tearDown lifecycle method is called
Loading an auditor into the container
An auditor is bound into the container at build time using the EventProcessorConfig
instance that is provided in one of the overloaded Fluxtion build methods. The auditor instance must be registered with
a name that is unique for the container.
Implementing the auditor
The SystemStatisticsAuditor implements Auditor and calculates the
monitoring statistics we want to report. The exported service method publishStats creates the report and publishes it
to the console. For our auditor to be useful it needs to interact with the outside world, in this example we provide
two ways for publishStats to be called.
SystemStatisticsAuditor implements the lifecycle tearDown method that chains a call to publishStats() on shutdown
SystemStatisticsAuditor exports the service SystemMonitor, application code can locate the auditor’s exported service and call publishStats on demand
We won’t discuss the calculation in detail, but important points to note are how the monitoring callbacks are used to
drive the statistics we want to capture.
nodeRegistered - builds an IdentityHashMap of node instances that will be used to record node stats
eventReceived - calculates the client to container event call statistics
nodeInvoked - builds the method invocation statistics for a node
Building the application
As Fluxtion is in aot mode the serialised LotteryProcessor can be inspected
to locate where the notification callbacks to the auditor are injected.
A FluxtionSpringConfig bean is added to the spring
config file that references the SystemStatisticsAuditor we want to include in the event processor. A specialised handler
for FluxtionSpringConfig customises the generated event processor by calling methods on
the EventProcessorConfig at build time.
The Fluxtion maven plugin will run as part of the build, logging this output as part of the build:
Running the application
The lottery application has a few changes from the second tutorial:
LotteryEventProcessor instance is assigned to a member variable
App code calls LotterySystemMonitor::publishStats on the exported service during execution
Teardown of the container is called, lotteryEventProcessor.tearDown(), that forces a final stats publication from the auditor
Logging has been removed from the beans TicketStoreNode and LotteryMachineNode to reduce output
Our updated LotteryApp looks like this:
Executing our application produces different output from the second tutorial. The statistics output from the auditor
is published twice to the console, one driven by user code and the other by teardown lifecycle.
The detailed breakdown of the stats are for the reader to analyse, but you should be able to see that detailed
calculations can be carried out by the auditor to assess how the user code is being used at runtime by the container.
For the lotteryMachine instance the teardown stats tell us:
In this tutorial we have seen how a custom auditor can be injected into the container and used to monitor runtime
performance without any changes required to the business code. With very little effort the following benefits are
realised:
Applications can be monitored at runtime without any changes to app code
A range of auditors with specific goals can be developed and re-used across multiple applications
Auditors bound to the container can easily be changed independently of application code
Alerts can be published from auditors if necessary giving early warning of problems
The impact of auditing in aot mode is very low as it is statically compiled into the container
I hope you have enjoyed reading this tutorial, and it has given you a desire to try adding auditing to your applications
. Please send me any comments or suggestions to improve this tutorial