Controlling logging in a running JVM can be awkward. The de facto method for administration of a running JVM is Java Management Extensions, but JMX has been awkward to use because it's traditionally had a focus on static interfaces and annotations, and was confusing at best to implement.
Despite that, it's entirely possible to put together a grab bag of attributes and operations from any place you like and have it exposed and registered to the system, using the DynamicBean API. Likewise, you don't need to worry about how to expose that information using the MXBean API together with the OpenData mapping, which restricts data types to a "JSON like" set of String, Number, java.util.Date and CompositeData and TabularData, which fulfill roughly the position of JSON objects and arrays.
This makes logging and debugging much easier, because you add functionality to all your components by putting together a builder with some components. You can then go in and change logging on an individual component.
First, we set up SBT so that it's running Jolokia and has the client and jmxbuilder available:
Then we can define a LoggingComponent with getLoggingLevel and setLoggingLevel:
Then we set up a DynamicBean.builder with some level values, using jmxbuilder:
We set up a JMXServer so that we can unregister the bean when the Play application is unloaded. We need this because in development mode, Play will close and recreate the Application inside the same JVM with a different classloader, so we need to clean up any references.
And then finally we set up a registerWithJMX method, and expose a protected decorateBean method so that different controllers can add extra attributes and operations to the dynamic bean.
For rendering logging events, we're going to pull information from Logback, expose it as a TabularData attribute, and then query it using the Jolokia client.
First, we define the LoggingEventsBean:
Then, we define the dynamic bean mapping:
and then finally we have a query service talk to Jolokia and pull on the exposed tabular data to display it locally:
After that, we just have to extend as per normal and all the functionality is hidden under the hood:
and then we can see the cyclic buffer when we go to http://localhost:9000, and we get this when we bring up Hawt in console:
I've also been poking at automatic registration of components with JMX. There's an old Sun project called Dynamic Management Kit which was open sourced and left on the wayside by Oracle. I found the documentation, tracked down an example of a virtual mbean interceptor, and broke it out into jmxmvc. This lets me do things like automatically register Akka actors in JMX:
I don't claim to say that this is useful, but it's fun, and I enjoy bricolage, so why not.