Problem statement: Expose Latency, Error-Rate, Throughput, Retry-Count (For persisting into SQL DB failures and Kafka publishing failures), and Unsuccessful-Retries of the Spring Boot application as ManagedBeans on JConsole. There are no REST endpoints in this application. It is purely asynchronously event-driven via Kafka (Use of Spring StreamListener).
I cannot use Prometheus due to the licensing issue on the Production level.
My Approach: Created a MetricsBean class (implementing an interface) essentially containing the POJO for the above metrics:
import org.springframework.context.annotation.Lazy;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource;
@Lazy(false)
@ManagedResource
public class ConfigMBean implements IConfigMBean {
private Double latency;
private Double errorRate;
private Double throughput;
private Long retryCount;
private Long unsuccessfulRetries;
public GatewayConfigMBean(Double latency, Double errorRate, Double throughput, Long retryCount,
Long unsuccessfulRetries) {
super();
this.latency = latency;
this.errorRate = errorRate;
this.throughput = throughput;
this.retryCount = retryCount;
this.unsuccessfulRetries = unsuccessfulRetries;
}
public GatewayConfigMBean() {
}
@ManagedAttribute
@Override
public Double getLatency() {
return latency;
}
@ManagedAttribute
@Override
public Double getErrorRate() {
return errorRate;
}
@ManagedAttribute
@Override
public Double getThroughput() {
return throughput;
}
@ManagedAttribute
@Override
public Long getRetryCount() {
return retryCount;
}
@ManagedAttribute
@Override
public Long getUnsuccessfulRetries() {
return unsuccessfulRetries;
}
@ManagedOperation
@Override
public String showMetrics() {
StringBuilder builder = new StringBuilder();
builder.append("GatewayConfigMBean [errorRate=").append(errorRate).append(", latency=").append(latency)
.append(", retryCount=").append(retryCount).append(", throughput=").append(throughput)
.append(", unsuccessfulRetries=").append(unsuccessfulRetries).append("]");
return builder.toString();
}
}
Then I exposed this Bean in the Config class:
@Bean("My_Microservice_Name")
public ConfigMBean configMBean () {
return new ConfigMBean ();
}
I was able to see My_Microservice_Name on the JConsole MBeans tab, but as expected all values were null.
Question: How to use Spring Micrometer to have correct values assigned to these metrics each? Also if I need to use some kind of AOP to get these metrics, how I need to incorporate that in my code?
I was searching on the internet and found a few hits:
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.Metrics;
private Counter counter = Metrics.counter("ErrorCount");
counter.increment();
private Timer timer = Metrics.timer("Latency");
// Assume startTime was declared earlier
timer.record(System.nanoTime() - startTime, TimeUnit.NANOSECONDS);
But not sure how to get the other Metrics and set these values to ConfigMBean class? Assume all dependencies are available for use in Spring. Need help with the above queries, please mention if any other information is also required.