title: gauge-like calculation of DistributionSummary with micrometer and prometheus
body: <p>I want to get a DistributionSummary over some domain data that does not change very frequently. So it is not about monitoring requests or sth like that. </p>
  
  <p>Let's take <em>number of seats in an office</em> as example. The value for each office can change from time to time and there can be new offices and also offices get removed.</p>
  
  <p>So now I need the current DistributionSummary over all offices, which needs to be calculated every time I think (similar to a Gauge).</p>
  
  <p>I have a Spring Boot 2 app with micrometer and collect the metrics with prometheus and display them in grafana.</p>
  
  <p>What I tried so far:</p>
  
  <p>When I register a DistributionSummary, I can record all the values once during startup... this gives me the distribution, but calculated values like <em>max</em> get lost over time and I cannot update the DistributionSummary (recording new offices would work, but not changing existing ones)</p>
  
  <pre><code>// during startup
  seatsInOffice = DistributionSummary.builder("office.seats")
      .publishPercentileHistogram()
      .sla(1, 5, 20, 50)
      .register(meterRegistry);
  
  officeService.getAllOffices().forEach(p -&gt; seatsInOffice.record(o.getNumberOfSeats()));
  </code></pre>
  
  <p>I also tried to use a <code>@Scheduled</code> task to remove and completely rebuild the DistributionSummary. This seems to work, but feels wrong somehow. Would that be a recommended approach? That would also probably need some synchronisation to not collect the metrics between removing and recalculating distribution.</p>
  
  <pre><code>@Scheduled(fixedRate = 5 * 60 * 1000)
  public void recalculateMetrics() {
      if (seatsInOffice != null) {
         meterRegistry.remove(seatsInOffice);
      }
      seatsInOffice = DistributionSummary.builder("office.seats")
          .publishPercentileHistogram()
          .sla(1, 5, 20, 50)
          .register(meterRegistry);
  
      officeService.getAllOffices().forEach(p -&gt; seatsInOffice.record(o.getNumberOfSeats()));
  }
  </code></pre>
  
  <p>Another problem I just recognized with this approach: the <code>/actuator/prometheus</code> endpoint still returns the values for the old (removed) metrics, so everything is there mutiple times.</p>
  
  <p>For sth like sla borders I could also use some gauges to provide the values (by calculating them myself), but that would not give me quantiles. Is it possible to create a new DistributionSummary without registering it and just provide the values it collected somehow?</p>
  
  <pre><code>meterRegistry.gauge("office.seats", Tags.of("le", "1"), officeService,
      x -&gt; x.getAllOfficesWithLessThanXSeats(1).size());
  meterRegistry.gauge("office.seats", Tags.of("le", "5"), officeService,
      x -&gt; x.getAllOfficesWithLessThanXSeats(5).size());
  meterRegistry.gauge("office.seats", Tags.of("le", "20"), officeService,
      x -&gt; x.getAllOfficesWithLessThanXSeats(20).size());
  meterRegistry.gauge("office.seats", Tags.of("le", "50"), officeService,
      x -&gt; x.getAllOfficesWithLessThanXSeats(50).size());
  </code></pre>
  
  <p>I would like to have a DistributionSummary that takes a lambda or sth like that to get the values. But maybe these tools are not made for this usecase and I should use sth else. Can you recommend sth?</p>