package io.prometheus.client; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.List; import org.junit.After; import org.junit.Before; import org.junit.Test; public class HistogramTest { CollectorRegistry registry; Histogram noLabels, labels; @Before public void setUp() { registry = new CollectorRegistry(); noLabels = Histogram.build().name("nolabels").help("help").register(registry); labels = Histogram.build().name("labels").help("help").labelNames("l").register(registry); } @After public void tearDown() { SimpleTimer.defaultTimeProvider = new SimpleTimer.TimeProvider(); } private double getCount() { return registry.getSampleValue("nolabels_count").doubleValue(); } private double getSum() { return registry.getSampleValue("nolabels_sum").doubleValue(); } private double getBucket(double b) { return registry.getSampleValue("nolabels_bucket", new String[]{"le"}, new String[]{Collector.doubleToGoString(b)}).doubleValue(); } @Test public void testObserve() { noLabels.observe(2); assertEquals(1.0, getCount(), .001); assertEquals(2.0, getSum(), .001); assertEquals(0.0, getBucket(1), .001); assertEquals(1.0, getBucket(2.5), .001); noLabels.labels().observe(4); assertEquals(2.0, getCount(), .001); assertEquals(6.0, getSum(), .001); assertEquals(0.0, getBucket(1), .001); assertEquals(1.0, getBucket(2.5), .001); assertEquals(2.0, getBucket(5), .001); assertEquals(2.0, getBucket(7.5), .001); assertEquals(2.0, getBucket(10), .001); assertEquals(2.0, getBucket(Double.POSITIVE_INFINITY), .001); } @Test public void testBoundaryConditions() { // Equal to a bucket. noLabels.observe(2.5); assertEquals(0.0, getBucket(1), .001); assertEquals(1.0, getBucket(2.5), .001); noLabels.labels().observe(Double.POSITIVE_INFINITY); // Infinity. assertEquals(0.0, getBucket(1), .001); assertEquals(1.0, getBucket(2.5), .001); assertEquals(1.0, getBucket(5), .001); assertEquals(1.0, getBucket(7.5), .001); assertEquals(1.0, getBucket(10), .001); assertEquals(2.0, getBucket(Double.POSITIVE_INFINITY), .001); } @Test public void testManualBuckets() { Histogram h = Histogram.build().name("h").help("help").buckets(1, 2).create(); assertArrayEquals(new double[]{1, 2, Double.POSITIVE_INFINITY}, h.getBuckets(), .001); } @Test public void testManualBucketsInfinityAlreadyIncluded() { Histogram h = Histogram.build().buckets(1, 2, Double.POSITIVE_INFINITY).name("h").help("help").create(); assertArrayEquals(new double[]{1, 2, Double.POSITIVE_INFINITY}, h.getBuckets(), .001); } @Test public void testLinearBuckets() { Histogram h = Histogram.build().name("h").help("help").linearBuckets(1, 2, 3).create(); assertArrayEquals(new double[]{1, 3, 5, Double.POSITIVE_INFINITY}, h.getBuckets(), .001); } @Test public void testExponentialBuckets() { Histogram h = Histogram.build().name("h").help("help").exponentialBuckets(2, 2.5, 3).create(); assertArrayEquals(new double[]{2, 5, 12.5, Double.POSITIVE_INFINITY}, h.getBuckets(), .001); } @Test public void testTimer() { SimpleTimer.defaultTimeProvider = new SimpleTimer.TimeProvider() { long value = (long)(30 * 1e9); long nanoTime() { value += (long)(10 * 1e9); return value; } }; double elapsed = noLabels.time(new Runnable() { @Override public void run() { //no op } }); assertEquals(10, elapsed, .001); Histogram.Timer timer = noLabels.startTimer(); elapsed = timer.observeDuration(); assertEquals(2, getCount(), .001); assertEquals(20, getSum(), .001); assertEquals(10, elapsed, .001); } @Test public void noLabelsDefaultZeroValue() { assertEquals(0.0, getCount(), .001); assertEquals(0.0, getSum(), .001); } private Double getLabelsCount(String labelValue) { return registry.getSampleValue("labels_count", new String[]{"l"}, new String[]{labelValue}); } private Double getLabelsSum(String labelValue) { return registry.getSampleValue("labels_sum", new String[]{"l"}, new String[]{labelValue}); } @Test public void testLabels() { assertEquals(null, getLabelsCount("a")); assertEquals(null, getLabelsSum("a")); assertEquals(null, getLabelsCount("b")); assertEquals(null, getLabelsSum("b")); labels.labels("a").observe(2); assertEquals(1.0, getLabelsCount("a").doubleValue(), .001); assertEquals(2.0, getLabelsSum("a").doubleValue(), .001); assertEquals(null, getLabelsCount("b")); assertEquals(null, getLabelsSum("b")); labels.labels("b").observe(3); assertEquals(1.0, getLabelsCount("a").doubleValue(), .001); assertEquals(2.0, getLabelsSum("a").doubleValue(), .001); assertEquals(1.0, getLabelsCount("b").doubleValue(), .001); assertEquals(3.0, getLabelsSum("b").doubleValue(), .001); } @Test(expected=IllegalStateException.class) public void testLeLabelThrows() { Histogram.build().name("labels").help("help").labelNames("le").create(); } @Test public void testCollect() { labels.labels("a").observe(2); List<Collector.MetricFamilySamples> mfs = labels.collect(); ArrayList<Collector.MetricFamilySamples.Sample> samples = new ArrayList<Collector.MetricFamilySamples.Sample>(); ArrayList<String> labelNames = new ArrayList<String>(); labelNames.add("l"); ArrayList<String> labelValues = new ArrayList<String>(); labelValues.add("a"); ArrayList<String> labelNamesLe = new ArrayList<String>(labelNames); labelNamesLe.add("le"); for (String bucket: new String[]{"0.005", "0.01", "0.025", "0.05", "0.075", "0.1", "0.25", "0.5", "0.75", "1.0"}) { ArrayList<String> labelValuesLe = new ArrayList<String>(labelValues); labelValuesLe.add(bucket); samples.add(new Collector.MetricFamilySamples.Sample("labels_bucket", labelNamesLe, labelValuesLe, 0.0)); } for (String bucket: new String[]{"2.5", "5.0", "7.5", "10.0", "+Inf"}) { ArrayList<String> labelValuesLe = new ArrayList<String>(labelValues); labelValuesLe.add(bucket); samples.add(new Collector.MetricFamilySamples.Sample("labels_bucket", labelNamesLe, labelValuesLe, 1.0)); } samples.add(new Collector.MetricFamilySamples.Sample("labels_count", labelNames, labelValues, 1.0)); samples.add(new Collector.MetricFamilySamples.Sample("labels_sum", labelNames, labelValues, 2.0)); Collector.MetricFamilySamples mfsFixture = new Collector.MetricFamilySamples("labels", Collector.Type.HISTOGRAM, "help", samples); assertEquals(1, mfs.size()); assertEquals(mfsFixture, mfs.get(0)); } @Test public void testChildAndValuePublicApi() throws Exception { assertTrue(Modifier.isPublic(Histogram.Child.class.getModifiers())); final Method getMethod = Histogram.Child.class.getMethod("get"); assertTrue(Modifier.isPublic(getMethod.getModifiers())); assertEquals(Histogram.Child.Value.class, getMethod.getReturnType()); assertTrue(Modifier.isPublic(Histogram.Child.Value.class.getModifiers())); assertTrue(Modifier.isPublic(Histogram.Child.Value.class.getField("sum").getModifiers())); assertTrue(Modifier.isPublic(Histogram.Child.Value.class.getField("buckets").getModifiers())); } }