public static Collection<PreaggregatedMetric> convertTimers(String tenant, long timestamp, Collection<BluefloodTimer> timers) { List<PreaggregatedMetric> list = new ArrayList<PreaggregatedMetric>(timers.size()); for (BluefloodTimer timer : timers) { Locator locator = Locator.createLocatorFromPathComponents(tenant, timer.getName().split(NAME_DELIMITER, -1)); BluefloodTimerRollup rollup = new BluefloodTimerRollup() .withCount(timer.getCount().longValue()) .withSampleCount(1) .withAverage(resolveNumber(timer.getAvg() == null ? 0.0d : timer.getAvg())) .withMaxValue(resolveNumber(timer.getMax() == null ? 0.0d : timer.getMax())) .withMinValue(resolveNumber(timer.getMin() == null ? 0.0d : timer.getMin())) .withCountPS(timer.getRate() == null ? 0.0d : timer.getRate().doubleValue()) .withSum(timer.getSum() == null ? 0L : timer.getSum().doubleValue()) .withVariance(Math.pow(timer.getStd() == null ? 0.0d : timer.getStd().doubleValue(), 2d)); for (Map.Entry<String, Percentile> entry : timer.getPercentiles().entrySet()) { // throw away max and sum. if (entry.getValue().getAvg() != null) { rollup.setPercentile(entry.getKey(), resolveNumber(entry.getValue().getAvg())); } } PreaggregatedMetric metric = new PreaggregatedMetric(timestamp, locator, DEFAULT_TTL, rollup); list.add(metric); } return list; }
@Test public void testHistograms() { AggregatedPayload payload = new Gson().fromJson(json, AggregatedPayload.class); assertNotNull(payload); Map<String, BluefloodTimer> timers = asMap(payload.getTimers()); assertEquals(4, timers.get( "4444444.T1s" + postfix ).getHistogram().size()); assertEquals(11, timers.get( "3333333.T29s" + postfix ).getHistogram().size()); assertEquals(11, timers.get( "3333333.T200ms" + postfix ).getHistogram().size()); // this one is non-existant in the json, but we do not want a null map. assertNotNull(timers.get( "3333333.T10s" + postfix ).getHistogram()); assertEquals(0, timers.get( "3333333.T10s" + postfix ).getHistogram().size()); }
private static Map<String, BluefloodTimer> asMap(Collection<BluefloodTimer> timers) { Map<String, BluefloodTimer> map = new HashMap<String, BluefloodTimer>(timers.size()); for (BluefloodTimer timer : timers) map.put(timer.getName(), timer); return map; } }
@Test public void testPercentiles() { AggregatedPayload payload = new Gson().fromJson(json, AggregatedPayload.class); assertNotNull(payload); Map<String, BluefloodTimer> timers = asMap(payload.getTimers()); assertEquals(5, timers.get( "4444444.T1s" + postfix ).getPercentiles().size()); assertEquals(5, timers.get( "3333333.T29s" + postfix ).getPercentiles().size()); assertEquals(5, timers.get( "3333333.T10s" + postfix ).getPercentiles().size()); assertEquals(5, timers.get( "3333333.T200ms" + postfix ).getPercentiles().size()); }
@Test public void testValidTimer() throws IOException { BluefloodTimer timer = new BluefloodTimer("timer.a.b", 5); FullHttpRequest request = createIngestRequest(createRequestBody(TENANT, new DefaultClockImpl().now().getMillis(), 0, null, null, new BluefloodTimer[]{timer}, null)); ArgumentCaptor<FullHttpResponse> argument = ArgumentCaptor.forClass(FullHttpResponse.class); handler.handle(context, request); verify(channel).write(argument.capture()); String responseBody = argument.getValue().content().toString(Charset.defaultCharset()); assertEquals("Invalid response", "", responseBody); assertEquals("Invalid status", HttpResponseStatus.OK, argument.getValue().getStatus()); }
@Test public void testTimerEmptyMetricName() throws IOException { BluefloodTimer timer = new BluefloodTimer("", 5); FullHttpRequest request = createIngestRequest(createRequestBody(TENANT, new DefaultClockImpl().now().getMillis(), 0, null, null, new BluefloodTimer[]{timer}, null)); ArgumentCaptor<FullHttpResponse> argument = ArgumentCaptor.forClass(FullHttpResponse.class); handler.handle(context, request); verify(channel).write(argument.capture()); String errorResponseBody = argument.getValue().content().toString(Charset.defaultCharset()); ErrorResponse errorResponse = getErrorResponse(errorResponseBody); assertEquals("Number of errors invalid", 1, errorResponse.getErrors().size()); assertEquals("Invalid error message", "may not be empty", errorResponse.getErrors().get(0).getMessage()); assertEquals("Invalid source", "timers[0].name", errorResponse.getErrors().get(0).getSource()); assertEquals("Invalid tenant", TENANT, errorResponse.getErrors().get(0).getTenantId()); assertEquals("Invalid status", HttpResponseStatus.BAD_REQUEST, argument.getValue().getStatus()); }
@Test public void testTimerEmptyMetricCount() throws IOException { String metricName = "timer.a.b"; BluefloodTimer timer = new BluefloodTimer(metricName, null); FullHttpRequest request = createIngestRequest(createRequestBody(TENANT, new DefaultClockImpl().now().getMillis(), 0, null, null, new BluefloodTimer[]{timer}, null)); ArgumentCaptor<FullHttpResponse> argument = ArgumentCaptor.forClass(FullHttpResponse.class); handler.handle(context, request); verify(channel).write(argument.capture()); String errorResponseBody = argument.getValue().content().toString(Charset.defaultCharset()); ErrorResponse errorResponse = getErrorResponse(errorResponseBody); assertEquals("Number of errors invalid", 1, errorResponse.getErrors().size()); assertEquals("Invalid error message", "may not be null", errorResponse.getErrors().get(0).getMessage()); assertEquals("Invalid source", "timers[0].count", errorResponse.getErrors().get(0).getSource()); assertEquals("Invalid tenant", TENANT, errorResponse.getErrors().get(0).getTenantId()); assertEquals("Invalid metric name", metricName, errorResponse.getErrors().get(0).getMetricName()); assertEquals("Invalid status", HttpResponseStatus.BAD_REQUEST, argument.getValue().getStatus()); }