diff --git a/.gitignore b/.gitignore index 2ddd19a..3b93205 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,8 @@ target *.iml .idea + +# Eclipse files +/.classpath +/.project +/.settings diff --git a/src/main/java/com/bealetech/metrics/reporting/StatsdReporter.java b/src/main/java/com/bealetech/metrics/reporting/StatsdReporter.java index 6d4cdb2..82b96bb 100644 --- a/src/main/java/com/bealetech/metrics/reporting/StatsdReporter.java +++ b/src/main/java/com/bealetech/metrics/reporting/StatsdReporter.java @@ -15,14 +15,11 @@ */ package com.bealetech.metrics.reporting; -import com.yammer.metrics.Metrics; -import com.yammer.metrics.core.*; -import com.yammer.metrics.reporting.AbstractPollingReporter; -import com.yammer.metrics.stats.Snapshot; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.*; +import java.io.BufferedWriter; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; @@ -31,24 +28,49 @@ import java.util.SortedMap; import java.util.concurrent.TimeUnit; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.yammer.metrics.Metrics; +import com.yammer.metrics.core.Clock; +import com.yammer.metrics.core.Counter; +import com.yammer.metrics.core.Gauge; +import com.yammer.metrics.core.Histogram; +import com.yammer.metrics.core.Metered; +import com.yammer.metrics.core.Metric; +import com.yammer.metrics.core.MetricName; +import com.yammer.metrics.core.MetricPredicate; +import com.yammer.metrics.core.MetricProcessor; +import com.yammer.metrics.core.MetricsRegistry; +import com.yammer.metrics.core.Sampling; +import com.yammer.metrics.core.Summarizable; +import com.yammer.metrics.core.Timer; +import com.yammer.metrics.core.VirtualMachineMetrics; +import com.yammer.metrics.reporting.AbstractPollingReporter; +import com.yammer.metrics.stats.Snapshot; + public class StatsdReporter extends AbstractPollingReporter implements MetricProcessor { public static enum StatType { COUNTER, TIMER, GAUGE } private static final Logger LOG = LoggerFactory.getLogger(StatsdReporter.class); - - protected final String prefix; - protected final MetricPredicate predicate; - protected final Locale locale = Locale.US; - protected final Clock clock; - protected final UDPSocketProvider socketProvider; - protected final VirtualMachineMetrics vm; - protected Writer writer; - protected ByteArrayOutputStream outputData; + + private static final int DEFAULT_MAX_UDP_PACKET_SIZE = 1500; + + private final String prefix; + private final MetricPredicate predicate; + private final Locale locale = Locale.US; + private final Clock clock; + private final UDPSocketProvider socketProvider; + private final VirtualMachineMetrics vm; + private ByteArrayOutputStream outputData; + private int udpPacketMaxSize; private boolean prependNewline = false; private boolean printVMMetrics = true; + private DatagramSocket socket; + public interface UDPSocketProvider { DatagramSocket get() throws Exception; DatagramPacket newPacket(ByteArrayOutputStream out); @@ -79,14 +101,19 @@ public StatsdReporter(MetricsRegistry metricsRegistry, String prefix, MetricPred } public StatsdReporter(MetricsRegistry metricsRegistry, String prefix, MetricPredicate predicate, UDPSocketProvider socketProvider, Clock clock, VirtualMachineMetrics vm) throws IOException { - this(metricsRegistry, prefix, predicate, socketProvider, clock, vm, "graphite-reporter"); + this(metricsRegistry, prefix, predicate, socketProvider, clock, vm, "statsd-reporter"); } public StatsdReporter(MetricsRegistry metricsRegistry, String prefix, MetricPredicate predicate, UDPSocketProvider socketProvider, Clock clock, VirtualMachineMetrics vm, String name) throws IOException { + this(metricsRegistry, prefix, predicate, socketProvider, clock, vm, name, DEFAULT_MAX_UDP_PACKET_SIZE); + } + + public StatsdReporter(MetricsRegistry metricsRegistry, String prefix, MetricPredicate predicate, UDPSocketProvider socketProvider, Clock clock, VirtualMachineMetrics vm, String name, int udpPacketMaxSize) throws IOException { super(metricsRegistry, name); this.socketProvider = socketProvider; this.vm = vm; + this.udpPacketMaxSize = udpPacketMaxSize; this.clock = clock; @@ -110,12 +137,8 @@ public void setPrintVMMetrics(boolean printVMMetrics) { @Override public void run() { - DatagramSocket socket = null; try { socket = this.socketProvider.get(); - outputData.reset(); - prependNewline = false; - writer = new BufferedWriter(new OutputStreamWriter(this.outputData)); final long epoch = clock.time() / 1000; if (this.printVMMetrics) { @@ -123,33 +146,33 @@ public void run() { } printRegularMetrics(epoch); - // Send UDP data - writer.flush(); - DatagramPacket packet = this.socketProvider.newPacket(outputData); - packet.setData(outputData.toByteArray()); - socket.send(packet); + sendUDPData(); } catch (Exception e) { if (LOG.isDebugEnabled()) { - LOG.debug("Error writing to Graphite", e); + LOG.debug("Error writing to Statsd", e); } else { - LOG.warn("Error writing to Graphite: {}", e.getMessage()); - } - if (writer != null) { - try { - writer.flush(); - } catch (IOException e1) { - LOG.error("Error while flushing writer:", e1); - } + LOG.warn("Error writing to Statsd: {}", e.getMessage()); } } finally { if (socket != null) { socket.close(); } - writer = null; } + socket = null; } - protected void printVmMetrics(long epoch) { + private void sendUDPData() throws IOException { + // Send UDP data + outputData.flush(); + DatagramPacket packet = this.socketProvider.newPacket(outputData); + packet.setData(outputData.toByteArray()); + socket.send(packet); + + outputData.reset(); + prependNewline = false; + } + + private void printVmMetrics(long epoch) { // Memory sendFloat("jvm.memory.totalInit", StatType.GAUGE, vm.totalInit()); sendFloat("jvm.memory.totalUsed", StatType.GAUGE, vm.totalUsed()); @@ -196,7 +219,7 @@ protected void printVmMetrics(long epoch) { } } - protected void printRegularMetrics(long epoch) { + private void printRegularMetrics(long epoch) { for (Map.Entry> entry : getMetricsRegistry().groupedMetrics(predicate).entrySet()) { for (Map.Entry subEntry : entry.getValue().entrySet()) { final Metric metric = subEntry.getValue(); @@ -246,14 +269,14 @@ public void processGauge(MetricName name, Gauge gauge, Long epoch) throws Exc sendObj(sanitizeName(name) + ".count", StatType.GAUGE, gauge.value()); } - protected void sendSummarizable(String sanitizedName, Summarizable metric) throws IOException { + private void sendSummarizable(String sanitizedName, Summarizable metric) throws IOException { sendFloat(sanitizedName + ".min", StatType.TIMER, metric.min()); sendFloat(sanitizedName + ".max", StatType.TIMER, metric.max()); sendFloat(sanitizedName + ".mean", StatType.TIMER, metric.mean()); sendFloat(sanitizedName + ".stddev", StatType.TIMER, metric.stdDev()); } - protected void sendSampling(String sanitizedName, Sampling metric) throws IOException { + private void sendSampling(String sanitizedName, Sampling metric) throws IOException { final Snapshot snapshot = metric.getSnapshot(); sendFloat(sanitizedName + ".median", StatType.TIMER, snapshot.getMedian()); sendFloat(sanitizedName + ".75percentile", StatType.TIMER, snapshot.get75thPercentile()); @@ -264,19 +287,19 @@ protected void sendSampling(String sanitizedName, Sampling metric) throws IOExce } - protected void sendInt(String name, StatType statType, long value) { + private void sendInt(String name, StatType statType, long value) { sendData(name, String.format(locale, "%d", value), statType); } - protected void sendFloat(String name, StatType statType, double value) { + private void sendFloat(String name, StatType statType, double value) { sendData(name, String.format(locale, "%2.2f", value), statType); } - protected void sendObj(String name, StatType statType, Object value) { + private void sendObj(String name, StatType statType, Object value) { sendData(name, String.format(locale, "%s", value), statType); } - protected String sanitizeName(MetricName name) { + private String sanitizeName(MetricName name) { final StringBuilder sb = new StringBuilder() .append(name.getGroup()) .append('.') @@ -289,11 +312,11 @@ protected String sanitizeName(MetricName name) { return sb.append(name.getName()).toString(); } - protected String sanitizeString(String s) { + private static String sanitizeString(String s) { return s.replace(' ', '-'); } - protected void sendData(String name, String value, StatType statType) { + private void sendData(String name, String value, StatType statType) { String statTypeStr = ""; switch (statType) { case COUNTER: @@ -306,23 +329,30 @@ protected void sendData(String name, String value, StatType statType) { statTypeStr = "ms"; break; } - + + final StringBuffer toWrite = new StringBuffer(); + if (prependNewline) { + toWrite.append("\n"); + } + if (!prefix.isEmpty()) { + toWrite.append(prefix); + } + toWrite.append(sanitizeString(name)); + toWrite.append(":"); + toWrite.append(value); + toWrite.append("|"); + toWrite.append(statTypeStr); + prependNewline = true; + + final byte[] bytesToWrite = toWrite.toString().getBytes(); + try { - if (prependNewline) { - writer.write("\n"); - } - if (!prefix.isEmpty()) { - writer.write(prefix); + if (outputData.size() + bytesToWrite.length > this.udpPacketMaxSize) { + sendUDPData(); } - writer.write(sanitizeString(name)); - writer.write(":"); - writer.write(value); - writer.write("|"); - writer.write(statTypeStr); - prependNewline = true; - writer.flush(); + outputData.write(bytesToWrite); } catch (IOException e) { - LOG.error("Error sending to Graphite:", e); + LOG.error("Error sending to Statsd:", e); } } diff --git a/src/test/java/com/bealetech/metrics/reporting/StatsdReporterTest.java b/src/test/java/com/bealetech/metrics/reporting/StatsdReporterTest.java index e1906b6..57ad23b 100644 --- a/src/test/java/com/bealetech/metrics/reporting/StatsdReporterTest.java +++ b/src/test/java/com/bealetech/metrics/reporting/StatsdReporterTest.java @@ -15,14 +15,12 @@ */ package com.bealetech.metrics.reporting; -import com.yammer.metrics.core.*; -import com.yammer.metrics.reporting.AbstractPollingReporter; -import com.yammer.metrics.stats.Snapshot; -import org.junit.Before; -import org.junit.Test; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; -import org.mockito.stubbing.Stubber; +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import java.io.ByteArrayOutputStream; import java.net.DatagramPacket; @@ -32,18 +30,41 @@ import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; -import static org.junit.Assert.assertEquals; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.*; +import junit.framework.Assert; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.mockito.stubbing.Stubber; + +import com.yammer.metrics.core.Clock; +import com.yammer.metrics.core.Counter; +import com.yammer.metrics.core.Gauge; +import com.yammer.metrics.core.Histogram; +import com.yammer.metrics.core.Meter; +import com.yammer.metrics.core.Metered; +import com.yammer.metrics.core.Metric; +import com.yammer.metrics.core.MetricName; +import com.yammer.metrics.core.MetricPredicate; +import com.yammer.metrics.core.MetricProcessor; +import com.yammer.metrics.core.MetricsRegistry; +import com.yammer.metrics.core.Sampling; +import com.yammer.metrics.core.Summarizable; +import com.yammer.metrics.core.Timer; +import com.yammer.metrics.reporting.AbstractPollingReporter; +import com.yammer.metrics.stats.Snapshot; public class StatsdReporterTest { - protected final Clock clock = mock(Clock.class); - protected AbstractPollingReporter reporter; - protected TestMetricsRegistry registry; - protected DatagramPacket packet; + private final Clock clock = mock(Clock.class); + private AbstractPollingReporter reporter; + private TestMetricsRegistry registry; + private DatagramPacket packet; + private DatagramPacket secondPacket; + private DatagramSocket mockedSocket; - protected static class TestMetricsRegistry extends MetricsRegistry { + private static class TestMetricsRegistry extends MetricsRegistry { public T add(MetricName name, T metric) { return getOrAdd(name, metric); } @@ -54,16 +75,20 @@ public void init() throws Exception { when(clock.tick()).thenReturn(1234L); when(clock.time()).thenReturn(5678L); registry = new TestMetricsRegistry(); + byte[] data = new byte[65536]; packet = new DatagramPacket(data, data.length); + + byte[] secondData = new byte[65536]; + secondPacket = new DatagramPacket(secondData, secondData.length); reporter = createReporter(registry, clock); } - protected AbstractPollingReporter createReporter(MetricsRegistry registry, Clock clock) throws Exception { - final DatagramSocket socket = mock(DatagramSocket.class); + private AbstractPollingReporter createReporter(MetricsRegistry registry, Clock clock) throws Exception { + mockedSocket = mock(DatagramSocket.class); final StatsdReporter.UDPSocketProvider provider = mock(StatsdReporter.UDPSocketProvider.class); - when(provider.get()).thenReturn(socket); - when(provider.newPacket(any(ByteArrayOutputStream.class))).thenReturn(packet); + when(provider.get()).thenReturn(mockedSocket); + when(provider.newPacket(any(ByteArrayOutputStream.class))).thenReturn(packet).thenReturn(secondPacket); final StatsdReporter reporter = new StatsdReporter(registry, "prefix", @@ -74,85 +99,110 @@ protected AbstractPollingReporter createReporter(MetricsRegistry registry, Clock return reporter; } - protected void assertReporterOutput(Callable action, String... expected) throws Exception { + private void assertReporterOutput(Callable action, String[][] expected) throws Exception { // Invoke the callable to trigger (ie, mark()/inc()/etc) and return the metric final T metric = action.call(); + Assert.assertTrue(expected.length > 0); try { // Add the metric to the registry, run the reporter and flush the result registry.add(new MetricName(Object.class, "metric"), metric); reporter.run(); String packetData = new String(packet.getData()); - final String[] lines = packetData.split("\r?\n|\r"); - // Assertions: first check that the line count matches then compare line by line ignoring leading and trailing whitespace - assertEquals("Line count mismatch, was:\n" + Arrays.toString(lines) + "\nexpected:\n" + Arrays - .toString(expected) + "\n", expected.length, - lines.length); - for (int i = 0; i < lines.length; i++) { - if (!expected[i].trim().equals(lines[i].trim())) { - System.err.println("Failure comparing line " + (1 + i)); - System.err.println("Was: '" + lines[i] + "'"); - System.err.println("Expected: '" + expected[i] + "'\n"); - } - assertEquals(expected[i].trim(), lines[i].trim()); + String[] lines = packetData.split("\r?\n|\r"); + assertArraysTrimmedEquals(expected[0], lines); + if (expected.length > 1) { + packetData = new String(secondPacket.getData()); + lines = packetData.split("\r?\n|\r"); + assertArraysTrimmedEquals(expected[1], lines); } + + Assert.assertFalse("Test don't currently handle more than two generated packets. Should probably use a loop instead.", expected.length > 2); } finally { reporter.shutdown(); } + verify(mockedSocket).send(packet); + } + + private void assertArraysTrimmedEquals(String[] expected, String[] lines) { + // Assertions: first check that the line count matches then compare line by line ignoring leading and trailing whitespace + assertEquals("Line count mismatch, was:\n" + Arrays.toString(lines) + "\nexpected:\n" + Arrays + .toString(expected) + "\n", expected.length, + lines.length); + for (int i = 0; i < lines.length; i++) { + if (!expected[i].trim().equals(lines[i].trim())) { + System.err.println("Failure comparing line " + (1 + i)); + System.err.println("Was: '" + lines[i] + "'"); + System.err.println("Expected: '" + expected[i] + "'\n"); + } + assertEquals(expected[i].trim(), lines[i].trim()); + } } - public String[] expectedGaugeResult(String value) { - return new String[]{String.format("prefix.java.lang.Object.metric.count:%s|g", value)}; + public String[][] expectedGaugeResult(String value) { + return new String[][] { + new String[] { + String.format("prefix.java.lang.Object.metric.count:%s|g", value) + } + }; } - public String[] expectedTimerResult() { - return new String[]{ - "prefix.java.lang.Object.metric.count:1|g", - "prefix.java.lang.Object.metric.meanRate:2.00|ms", - "prefix.java.lang.Object.metric.1MinuteRate:1.00|ms", - "prefix.java.lang.Object.metric.5MinuteRate:5.00|ms", - "prefix.java.lang.Object.metric.15MinuteRate:15.00|ms", - "prefix.java.lang.Object.metric.min:1.00|ms", - "prefix.java.lang.Object.metric.max:3.00|ms", - "prefix.java.lang.Object.metric.mean:2.00|ms", - "prefix.java.lang.Object.metric.stddev:1.50|ms", - "prefix.java.lang.Object.metric.median:0.50|ms", - "prefix.java.lang.Object.metric.75percentile:0.75|ms", - "prefix.java.lang.Object.metric.95percentile:0.95|ms", - "prefix.java.lang.Object.metric.98percentile:0.98|ms", - "prefix.java.lang.Object.metric.99percentile:0.99|ms", - "prefix.java.lang.Object.metric.999percentile:1.00|ms" + public String[][] expectedTimerResult() { + return new String[][] { + new String[] { + "prefix.java.lang.Object.metric.count:1|g", + "prefix.java.lang.Object.metric.meanRate:2.00|ms", + "prefix.java.lang.Object.metric.1MinuteRate:1.00|ms", + "prefix.java.lang.Object.metric.5MinuteRate:5.00|ms", + "prefix.java.lang.Object.metric.15MinuteRate:15.00|ms", + "prefix.java.lang.Object.metric.min:1.00|ms", + "prefix.java.lang.Object.metric.max:3.00|ms", + "prefix.java.lang.Object.metric.mean:2.00|ms", + "prefix.java.lang.Object.metric.stddev:1.50|ms", + "prefix.java.lang.Object.metric.median:0.50|ms", + "prefix.java.lang.Object.metric.75percentile:0.75|ms", + "prefix.java.lang.Object.metric.95percentile:0.95|ms", + "prefix.java.lang.Object.metric.98percentile:0.98|ms", + "prefix.java.lang.Object.metric.99percentile:0.99|ms", + "prefix.java.lang.Object.metric.999percentile:1.00|ms" + } }; } - public String[] expectedMeterResult() { - return new String[]{ - "prefix.java.lang.Object.metric.count:1|g", - "prefix.java.lang.Object.metric.meanRate:2.00|ms", - "prefix.java.lang.Object.metric.1MinuteRate:1.00|ms", - "prefix.java.lang.Object.metric.5MinuteRate:5.00|ms", - "prefix.java.lang.Object.metric.15MinuteRate:15.00|ms", + public String[][] expectedMeterResult() { + return new String[][] { + new String[] { + "prefix.java.lang.Object.metric.count:1|g", + "prefix.java.lang.Object.metric.meanRate:2.00|ms", + "prefix.java.lang.Object.metric.1MinuteRate:1.00|ms", + "prefix.java.lang.Object.metric.5MinuteRate:5.00|ms", + "prefix.java.lang.Object.metric.15MinuteRate:15.00|ms", + } }; } - public String[] expectedHistogramResult() { - return new String[]{ - "prefix.java.lang.Object.metric.min:1.00|ms", - "prefix.java.lang.Object.metric.max:3.00|ms", - "prefix.java.lang.Object.metric.mean:2.00|ms", - "prefix.java.lang.Object.metric.stddev:1.50|ms", - "prefix.java.lang.Object.metric.median:0.50|ms", - "prefix.java.lang.Object.metric.75percentile:0.75|ms", - "prefix.java.lang.Object.metric.95percentile:0.95|ms", - "prefix.java.lang.Object.metric.98percentile:0.98|ms", - "prefix.java.lang.Object.metric.99percentile:0.99|ms", - "prefix.java.lang.Object.metric.999percentile:1.00|ms" + public String[][] expectedHistogramResult() { + return new String[][] { + new String[] { + "prefix.java.lang.Object.metric.min:1.00|ms", + "prefix.java.lang.Object.metric.max:3.00|ms", + "prefix.java.lang.Object.metric.mean:2.00|ms", + "prefix.java.lang.Object.metric.stddev:1.50|ms", + "prefix.java.lang.Object.metric.median:0.50|ms", + "prefix.java.lang.Object.metric.75percentile:0.75|ms", + "prefix.java.lang.Object.metric.95percentile:0.95|ms", + "prefix.java.lang.Object.metric.98percentile:0.98|ms", + "prefix.java.lang.Object.metric.99percentile:0.99|ms", + "prefix.java.lang.Object.metric.999percentile:1.00|ms" + } }; } - public String[] expectedCounterResult(long count) { - return new String[]{ + public String[][] expectedCounterResult(long count) { + return new String[][] { + new String[] { String.format("prefix.java.lang.Object.metric.count:%d|g", count) + } }; } @@ -218,7 +268,7 @@ public Gauge call() throws Exception { expectedGaugeResult(value)); } - static Counter createCounter(long count) throws Exception { + private static Counter createCounter(long count) throws Exception { final Counter mock = mock(Counter.class); when(mock.count()).thenReturn(count); return configureMatcher(mock, doAnswer(new MetricsProcessorAction() { @@ -229,7 +279,7 @@ void delegateToProcessor(MetricProcessor processor, MetricName name, Obj })); } - static Histogram createHistogram() throws Exception { + private static Histogram createHistogram() throws Exception { final Histogram mock = mock(Histogram.class); setupSummarizableMock(mock); setupSamplingMock(mock); @@ -242,7 +292,7 @@ void delegateToProcessor(MetricProcessor processor, MetricName name, Obj } - static Gauge createGauge() throws Exception { + private static Gauge createGauge() throws Exception { @SuppressWarnings("unchecked") final Gauge mock = mock(Gauge.class); when(mock.value()).thenReturn("gaugeValue"); @@ -255,7 +305,7 @@ void delegateToProcessor(MetricProcessor processor, MetricName name, Obj } - static Timer createTimer() throws Exception { + private static Timer createTimer() throws Exception { final Timer mock = mock(Timer.class); when(mock.durationUnit()).thenReturn(TimeUnit.MILLISECONDS); setupSummarizableMock(mock); @@ -269,7 +319,7 @@ void delegateToProcessor(MetricProcessor processor, MetricName name, Obj })); } - static Meter createMeter() throws Exception { + private static Meter createMeter() throws Exception { final Meter mock = mock(Meter.class); setupMeteredMock(mock); return configureMatcher(mock, doAnswer(new MetricsProcessorAction() { @@ -281,12 +331,12 @@ void delegateToProcessor(MetricProcessor processor, MetricName name, Obj } @SuppressWarnings("unchecked") - static T configureMatcher(T mock, Stubber stub) throws Exception { + private static T configureMatcher(T mock, Stubber stub) throws Exception { stub.when(mock).processWith(any(MetricProcessor.class), any(MetricName.class), any()); return mock; } - static abstract class MetricsProcessorAction implements Answer { + private static abstract class MetricsProcessorAction implements Answer { @Override public Object answer(InvocationOnMock invocation) throws Throwable { @SuppressWarnings("unchecked") @@ -300,14 +350,14 @@ public Object answer(InvocationOnMock invocation) throws Throwable { abstract void delegateToProcessor(MetricProcessor processor, MetricName name, Object context) throws Exception; } - static void setupSummarizableMock(Summarizable summarizable) { + private static void setupSummarizableMock(Summarizable summarizable) { when(summarizable.min()).thenReturn(1d); when(summarizable.max()).thenReturn(3d); when(summarizable.mean()).thenReturn(2d); when(summarizable.stdDev()).thenReturn(1.5d); } - static void setupMeteredMock(Metered metered) { + private static void setupMeteredMock(Metered metered) { when(metered.count()).thenReturn(1L); when(metered.oneMinuteRate()).thenReturn(1d); when(metered.fiveMinuteRate()).thenReturn(5d); @@ -317,7 +367,7 @@ static void setupMeteredMock(Metered metered) { when(metered.rateUnit()).thenReturn(TimeUnit.SECONDS); } - static void setupSamplingMock(Sampling sampling) { + private static void setupSamplingMock(Sampling sampling) { final double[] values = new double[1000]; for (int i = 0; i < values.length; i++) { values[i] = i / 1000.0;