Skip to content

Instantly share code, notes, and snippets.

@jrask
Created December 14, 2018 14:52
Show Gist options
  • Save jrask/52c70475ac744af56f88e43fab80a7c9 to your computer and use it in GitHub Desktop.
Save jrask/52c70475ac744af56f88e43fab80a7c9 to your computer and use it in GitHub Desktop.
Micrometer Histogram does not match timer.count
package se.flapsdown.micrometer.histograms.bug;
import io.micrometer.core.instrument.Clock;
import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.Timer;
import io.micrometer.core.instrument.distribution.CountAtBucket;
import io.micrometer.core.instrument.distribution.HistogramSnapshot;
import io.micrometer.core.instrument.step.StepMeterRegistry;
import io.micrometer.core.instrument.step.StepRegistryConfig;
import java.time.Duration;
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* This simple example shows how the histogram buckets does not match the timer.count value.
* It is expected that everything should fit within the buckets and that the value in the last
bucket should match the total count.
test_with_tag, , max:198.0, bucket: 100.0 = 82.0, bucket: 200.0 = 159.0, Count:163/163
test_with_tag, , max:198.0, bucket: 100.0 = 84.0, bucket: 200.0 = 159.0, Count:163/163
test_with_tag, , max:198.0, bucket: 100.0 = 74.0, bucket: 200.0 = 158.0, Count:162/162
test__no__tag, , max:198.0, bucket: 100.0 = 251.0, bucket: 200.0 = 485.0, Count:488/488
*/
public class PrintHistograms {
static StepRegistryConfig sc = new StepRegistryConfig() {
@Override
public Duration step() {
return Duration.ofSeconds(3);
}
@Override
public String prefix() {
return null;
}
@Override
public String get(String s) {
return null;
}
};
static StepMeterRegistry simpleRegistry = new StepMeterRegistry(sc, Clock.SYSTEM) {
@Override
protected TimeUnit getBaseTimeUnit() {
return TimeUnit.MILLISECONDS;
}
@Override
protected void publish() {
// Print info about each Timer and histogram
for (Meter m : getMeters()) {
if (m instanceof Timer) {
Timer t = (Timer)m;
HistogramSnapshot histogramSnapshot = t.takeSnapshot();
StringBuilder sb = new StringBuilder()
.append(getConventionName(t.getId())).append(", ")
.append(", max:").append(t.max(getBaseTimeUnit())) .append(", ");
for (CountAtBucket cab : histogramSnapshot.histogramCounts()) {
sb.append("bucket: ").append(cab.bucket(getBaseTimeUnit())).append(" = ").append(cab.count()).append(", ");
}
sb.append("Count:").append(t.count());
System.out.println(sb.toString());
}
}
}
};
public static void main(String args[]) throws InterruptedException {
simpleRegistry.start(Executors.defaultThreadFactory());
Random durationRandom = new Random();
int countTag = 0;
while (true != false) {
Timer.builder("test__no__tag")
.sla(Duration.ofMillis(100), Duration.ofMillis(200))
.register(simpleRegistry)
.record(Duration.ofMillis(durationRandom.nextInt(199)));
Timer.builder("test_with_tag")
.tag("count", countTag + "")
.sla(Duration.ofMillis(100), Duration.ofMillis(200))
.register(simpleRegistry)
.record(Duration.ofMillis(durationRandom.nextInt(199)));
TimeUnit.MILLISECONDS.sleep(5);
countTag++;
if (countTag > 2) {
countTag = 0;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment