Allow Tomcat's metrics to be bound when its MBean registry has been disabled
Tomcat 9.0.20 has introduced an option to disable its MBean registry. This improves startup time and reduces Tomcat's heap footprint by ~2MB. Spring Boot will disable the registry by default in 2.2.
A downside of disabling the registry is that a number of the MBeans that are used by TomcatMetrics are no longer available. We'll work around this in Boot by documenting that users should enable the registry if they want certain Tomcat metrics to be available. Assuming it's possible, I think it would be better if Micrometer was less reliant on Tomcat's MBeans for its Tomcat metrics. The HTTP session metrics do not rely on an MBean, perhaps some or even all of the others could take a similar approach?
I would love to not rely on MBeans at all if possible. I think we couldn't find alternatives for the rest. @markt-asf is there a way to retrieve the same information we're getting from the MBeans now? See TomcatMetrics. Specifically, we're using the Tomcat MBeans for ThreadPool, StringCache, Servlet, and GlobalRequestProcessor.
I would also note, though, that we've had requests from users to go the other direction and get session metrics from an MBean because when deploying as a WAR they don't have access to the Manager in application code (see #1620). The maintenance and testing of the code to retrieve from MBeans has been painful, though, and I'd prefer a strongly typed API.
There are various mechanisms. All involve some form of hack because they require jumping from application code to Tomcat's internals and Tomcat is designed to explicitly block that when running under a SecurityManager.
The simplest is probably implementing ContainerServlet which will give you access to the Wrapper (Tomcat's internal container for a Servlet) and from there you can navigate to wherever you wish. getParent() will get you the Context, another getParent() the Host and then the Engine. From there you can get to the Service and the Server which is the root of the object tree.
The other popular approach is cast a ServletContext to ApplicationContext and then use reflection to call getContext() and from there you have access to the same object hierarchy. While it uises reflection, it avoids the class loader requirements of ContainerServlet.
Hey @wilkinsona , are we supposed to do something about this in Micrometer or actually shouldn't it be done on the Framework / Boot side?
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
My hope was that this would be implemented entirely in Micrometer as an alternative to how TomcatMetrics works today. Disabling the MBean registry isn't Spring Boot-specific so I don't think that coping with it being disabled should be Spring Boot-specific either.
If an entry point is needed, such as a Wrapper instance, then that could be provided by the caller (as Manager is provided to TomcatMetrics at the moment) but, ideally, Micrometer should handle everything else.