0

I want to find the actual java class that serves the Spring Actuator endpoint (/actuator).

It's similar to this question in a way, but that person wanted to call it via a network HTTP call. Ideally, I can call it within the JVM to save on the cost of setting up an HTTP connection.

The reason for this is because we have 2 metrics frameworks in our system. We have a legacy metrics framework built on OpenCensus and we migrated to Spring Actuator (Prometheus metrics based on Micrometer). I think the Spring one is better but I didn't realize how much my company built infrastructure around the old one. For example, we leverage internal libraries that use OpenCensus. Infra team is depending on Opencensus-based metrics from our app. So the idea is to try to merge and report both sets of metrics.

I want to create my own metrics endpoint that pulls in data from Opencensus's endpoint and Actuator's endpoint. I could make an HTTP call to each, but I'd rather call them within the JVM to save on resources and reduce latency.

Or perhaps I'm thinking about it wrong. Should I simply be using MeterRegistry.forEachMeter() in my endpoint? In any case, I thought if I found the Spring Actuator endpoint, I can see an example of how they're doing it and mimic the implementation even if I don't call it directly.

Bonus: I'll need to track down the Opencensus handler that serves its endpoint too and will probably make another post for that, but if you know the answer to that as well, please share!

vasadia
  • 366
  • 5
  • 8
kane
  • 5,465
  • 6
  • 44
  • 72
  • Are you fine to just add OpenCensus data into Actuator periodically? That way you don't have to call Actuator methods at all, may be? – aksappy Jun 25 '21 at 19:57
  • Yes! I'm open to that as well – kane Jun 25 '21 at 20:24
  • Only thing is, micrometer likes to suffix its metrics (e.g. _count, _sum) and we need to preserve the original opencensus metrics names. So whatever soln has to account for that – kane Jun 25 '21 at 20:52

2 Answers2

0

I figured it out and posting this for anyone else interested.

The key finding: The MeterRegistry that is @Autowired is actually a PrometheusMeterRegistry if you enable the prometheus metrics.

Once you cast it into a PrometheusMeterRegistry, you can call its .scrape() method to return the exact same metrics printout you would when you hit the http endpoint.

I also need to get the same info from OpenCensus and I found a way to do that too.

Here's the snippet of code for getting metrics from both frameworks

Enumeration<MetricFamilySamples> openCensusSamples = CollectorRegistry.defaultRegistry.filteredMetricFamilySamples(ImmutableSet.of());
StringWriter writer = new StringWriter();
TextFormat.write004(writer, openCensusSamples);
String openCensusMetrics = writer.toString();

PrometheusMeterRegistry registry = (PrometheusMeterRegistry) meterRegistry;
String micrometerMetrics = registry.scrape();

return openCensusMetrics.concat(micrometerMetrics);
kane
  • 5,465
  • 6
  • 44
  • 72
0

I found out another interesting way of doing this.

The other answer I gave but it has one issue. It contains duplicate results. When I looked into it, I realized that both OpenCensus and Micrometer were reporting the same result.

Turns out that the PrometheusScrapeEndpoint implementation uses the same CollectorRegistry that OpenCensus does so the both sets of metrics were being added to the same registry.

You just need to make sure to provide these beans

@PostConstruct
public void openCensusStats() {
    PrometheusStatsCollector.createAndRegister();
}

@Bean
public CollectorRegistry collectorRegistry() {
  return CollectorRegistry.defaultRegistry;
}
kane
  • 5,465
  • 6
  • 44
  • 72