package io.dropwizard.metrics; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.io.UnsupportedEncodingException; import java.util.Collections; import java.util.Locale; import java.util.Map; import java.util.SortedMap; import java.util.TimeZone; import java.util.TreeMap; import java.util.concurrent.TimeUnit; import org.junit.Before; import org.junit.Test; public class ConsoleReporterTest { private final Map<String,String> testTags = Collections.singletonMap("key1", "value1"); private final MetricRegistry registry = mock(MetricRegistry.class); private final Clock clock = mock(Clock.class); private final ByteArrayOutputStream bytes = new ByteArrayOutputStream(); private final PrintStream output = new PrintStream(bytes); private final ConsoleReporter reporter = ConsoleReporter.forRegistry(registry) .outputTo(output) .formattedFor(Locale.US) .withClock(clock) .formattedFor(TimeZone.getTimeZone("PST")) .convertRatesTo(TimeUnit.SECONDS) .convertDurationsTo(TimeUnit.MILLISECONDS) .filter(MetricFilter.ALL) .withNameFormatter(name -> name.toString()) .build(); @Before public void setUp() throws Exception { when(clock.getTime()).thenReturn(1363568676000L); } @Test public void reportsGaugeValues() throws Exception { final Gauge gauge = mock(Gauge.class); when(gauge.getValue()).thenReturn(1); reporter.report(map("gauge", testTags, gauge), this.<Counter>map(), this.<Histogram>map(), this.<Meter>map(), this.<Timer>map()); assertThat(consoleOutput()) .isEqualTo(lines( "3/17/13 6:04:36 PM =============================================================", "", "-- Gauges ----------------------------------------------------------------------", "gauge{key1=value1}", " value = 1", "", "" )); } @Test public void reportsCounterValues() throws Exception { final Counter counter = mock(Counter.class); when(counter.getCount()).thenReturn(100L); reporter.report(this.<Gauge>map(), map("test.counter", testTags, counter), this.<Histogram>map(), this.<Meter>map(), this.<Timer>map()); assertThat(consoleOutput()) .isEqualTo(lines( "3/17/13 6:04:36 PM =============================================================", "", "-- Counters --------------------------------------------------------------------", "test.counter{key1=value1}", " count = 100", "", "" )); } @Test public void reportsHistogramValues() throws Exception { final Histogram histogram = mock(Histogram.class); when(histogram.getCount()).thenReturn(1L); final Snapshot snapshot = mock(Snapshot.class); when(snapshot.getMax()).thenReturn(2L); when(snapshot.getMean()).thenReturn(3.0); when(snapshot.getMin()).thenReturn(4L); when(snapshot.getStdDev()).thenReturn(5.0); when(snapshot.getMedian()).thenReturn(6.0); when(snapshot.get75thPercentile()).thenReturn(7.0); when(snapshot.get95thPercentile()).thenReturn(8.0); when(snapshot.get98thPercentile()).thenReturn(9.0); when(snapshot.get99thPercentile()).thenReturn(10.0); when(snapshot.get999thPercentile()).thenReturn(11.0); when(histogram.getSnapshot()).thenReturn(snapshot); reporter.report(this.<Gauge>map(), this.<Counter>map(), map("test.histogram", testTags, histogram), this.<Meter>map(), this.<Timer>map()); assertThat(consoleOutput()) .isEqualTo(lines( "3/17/13 6:04:36 PM =============================================================", "", "-- Histograms ------------------------------------------------------------------", "test.histogram{key1=value1}", " count = 1", " min = 4", " max = 2", " mean = 3.00", " stddev = 5.00", " median = 6.00", " 75% <= 7.00", " 95% <= 8.00", " 98% <= 9.00", " 99% <= 10.00", " 99.9% <= 11.00", "", "" )); } @Test public void reportsMeterValues() throws Exception { final Meter meter = mock(Meter.class); when(meter.getCount()).thenReturn(1L); when(meter.getMeanRate()).thenReturn(2.0); when(meter.getOneMinuteRate()).thenReturn(3.0); when(meter.getFiveMinuteRate()).thenReturn(4.0); when(meter.getFifteenMinuteRate()).thenReturn(5.0); reporter.report(this.<Gauge>map(), this.<Counter>map(), this.<Histogram>map(), map("test.meter", testTags, meter), this.<Timer>map()); assertThat(consoleOutput()) .isEqualTo(lines( "3/17/13 6:04:36 PM =============================================================", "", "-- Meters ----------------------------------------------------------------------", "test.meter{key1=value1}", " count = 1", " mean rate = 2.00 events/second", " 1-minute rate = 3.00 events/second", " 5-minute rate = 4.00 events/second", " 15-minute rate = 5.00 events/second", "", "" )); } @Test public void reportsTimerValues() throws Exception { final Timer timer = mock(Timer.class); when(timer.getCount()).thenReturn(1L); when(timer.getMeanRate()).thenReturn(2.0); when(timer.getOneMinuteRate()).thenReturn(3.0); when(timer.getFiveMinuteRate()).thenReturn(4.0); when(timer.getFifteenMinuteRate()).thenReturn(5.0); final Snapshot snapshot = mock(Snapshot.class); when(snapshot.getMax()).thenReturn(TimeUnit.MILLISECONDS.toNanos(100)); when(snapshot.getMean()).thenReturn((double) TimeUnit.MILLISECONDS.toNanos(200)); when(snapshot.getMin()).thenReturn(TimeUnit.MILLISECONDS.toNanos(300)); when(snapshot.getStdDev()).thenReturn((double) TimeUnit.MILLISECONDS.toNanos(400)); when(snapshot.getMedian()).thenReturn((double) TimeUnit.MILLISECONDS.toNanos(500)); when(snapshot.get75thPercentile()).thenReturn((double) TimeUnit.MILLISECONDS.toNanos(600)); when(snapshot.get95thPercentile()).thenReturn((double) TimeUnit.MILLISECONDS.toNanos(700)); when(snapshot.get98thPercentile()).thenReturn((double) TimeUnit.MILLISECONDS.toNanos(800)); when(snapshot.get99thPercentile()).thenReturn((double) TimeUnit.MILLISECONDS.toNanos(900)); when(snapshot.get999thPercentile()).thenReturn((double) TimeUnit.MILLISECONDS .toNanos(1000)); when(timer.getSnapshot()).thenReturn(snapshot); reporter.report(this.<Gauge>map(), this.<Counter>map(), this.<Histogram>map(), this.<Meter>map(), map("test.another.timer",testTags, timer)); assertThat(consoleOutput()) .isEqualTo(lines( "3/17/13 6:04:36 PM =============================================================", "", "-- Timers ----------------------------------------------------------------------", "test.another.timer{key1=value1}", " count = 1", " mean rate = 2.00 calls/second", " 1-minute rate = 3.00 calls/second", " 5-minute rate = 4.00 calls/second", " 15-minute rate = 5.00 calls/second", " min = 300.00 milliseconds", " max = 100.00 milliseconds", " mean = 200.00 milliseconds", " stddev = 400.00 milliseconds", " median = 500.00 milliseconds", " 75% <= 600.00 milliseconds", " 95% <= 700.00 milliseconds", " 98% <= 800.00 milliseconds", " 99% <= 900.00 milliseconds", " 99.9% <= 1000.00 milliseconds", "", "" )); } @Test public void testNameFormatterIsUsed() throws UnsupportedEncodingException { ConsoleReporter formatReporter = ConsoleReporter.forRegistry(registry) .outputTo(output) .formattedFor(Locale.US) .withClock(clock) .formattedFor(TimeZone.getTimeZone("PST")) .convertRatesTo(TimeUnit.SECONDS) .convertDurationsTo(TimeUnit.MILLISECONDS) .filter(MetricFilter.ALL) .withNameFormatter(MetricNameFormatter.APPEND_TAG_VALUES) .build(); final Counter counter = mock(Counter.class); when(counter.getCount()).thenReturn(100L); formatReporter.report(this.<Gauge>map(), map("test.counter", testTags, counter), this.<Histogram>map(), this.<Meter>map(), this.<Timer>map()); assertThat(consoleOutput()) .isEqualTo(lines( "3/17/13 6:04:36 PM =============================================================", "", "-- Counters --------------------------------------------------------------------", "test.counter.value1", " count = 100", "", "" )); } private String lines(String... lines) { final StringBuilder builder = new StringBuilder(); for (String line : lines) { builder.append(line).append(String.format("%n")); } return builder.toString(); } private String consoleOutput() throws UnsupportedEncodingException { return bytes.toString("UTF-8"); } private <T> SortedMap<MetricName, T> map() { return new TreeMap<>(); } private <T> SortedMap<MetricName, T> map(String name, Map<String,String> tags, T metric) { final TreeMap<MetricName, T> map = new TreeMap<>(); map.put(new MetricName(name,tags), metric); return map; } }