| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| package org.apache.druid.query; |
| |
| import com.google.common.collect.ImmutableMap; |
| import com.google.common.collect.ImmutableSet; |
| import org.apache.druid.java.util.common.granularity.Granularities; |
| import org.apache.druid.java.util.emitter.service.ServiceEmitter; |
| import org.apache.druid.query.aggregation.CountAggregatorFactory; |
| import org.apache.druid.query.dimension.DefaultDimensionSpec; |
| import org.apache.druid.query.dimension.ListFilteredDimensionSpec; |
| import org.apache.druid.query.filter.SelectorDimFilter; |
| import org.apache.druid.query.topn.TopNQuery; |
| import org.apache.druid.query.topn.TopNQueryBuilder; |
| import org.joda.time.Interval; |
| import org.junit.Assert; |
| import org.junit.Test; |
| |
| import java.util.List; |
| import java.util.Map; |
| import java.util.stream.Collectors; |
| |
| public class DefaultQueryMetricsTest |
| { |
| |
| /** |
| * Tests that passed a query {@link DefaultQueryMetrics} produces events with a certain set of dimensions, no more, |
| * no less. |
| */ |
| @Test |
| public void testDefaultQueryMetricsQuery() |
| { |
| CachingEmitter cachingEmitter = new CachingEmitter(); |
| ServiceEmitter serviceEmitter = new ServiceEmitter("", "", cachingEmitter); |
| DefaultQueryMetrics<Query<?>> queryMetrics = new DefaultQueryMetrics<>(); |
| TopNQuery query = new TopNQueryBuilder() |
| .dataSource("xx") |
| .granularity(Granularities.ALL) |
| .dimension(new ListFilteredDimensionSpec( |
| new DefaultDimensionSpec("tags", "tags"), |
| ImmutableSet.of("t3"), |
| null |
| )) |
| .metric("count") |
| .intervals(QueryRunnerTestHelper.FULL_ON_INTERVAL_SPEC) |
| .aggregators(new CountAggregatorFactory("count")) |
| .threshold(5) |
| .filters(new SelectorDimFilter("tags", "t3", null)) |
| .context(ImmutableMap.of("testKey", "testValue")) |
| .build(); |
| queryMetrics.query(query); |
| queryMetrics.reportQueryTime(0).emit(serviceEmitter); |
| Map<String, Object> actualEvent = cachingEmitter.getLastEmittedEvent().toMap(); |
| Assert.assertEquals(13, actualEvent.size()); |
| Assert.assertTrue(actualEvent.containsKey("feed")); |
| Assert.assertTrue(actualEvent.containsKey("timestamp")); |
| Assert.assertEquals("", actualEvent.get("host")); |
| Assert.assertEquals("", actualEvent.get("service")); |
| Assert.assertEquals("xx", actualEvent.get(DruidMetrics.DATASOURCE)); |
| Assert.assertEquals(query.getType(), actualEvent.get(DruidMetrics.TYPE)); |
| List<Interval> expectedIntervals = QueryRunnerTestHelper.FULL_ON_INTERVAL_SPEC.getIntervals(); |
| List<String> expectedStringIntervals = |
| expectedIntervals.stream().map(Interval::toString).collect(Collectors.toList()); |
| Assert.assertEquals(expectedStringIntervals, actualEvent.get(DruidMetrics.INTERVAL)); |
| Assert.assertEquals("true", actualEvent.get("hasFilters")); |
| Assert.assertEquals(expectedIntervals.get(0).toDuration().toString(), actualEvent.get("duration")); |
| Assert.assertEquals("", actualEvent.get(DruidMetrics.ID)); |
| Assert.assertEquals("query/time", actualEvent.get("metric")); |
| Assert.assertEquals(0L, actualEvent.get("value")); |
| Assert.assertEquals(ImmutableMap.of("testKey", "testValue"), actualEvent.get("context")); |
| } |
| |
| @Test |
| public void testDefaultQueryMetricsMetricNamesAndUnits() |
| { |
| CachingEmitter cachingEmitter = new CachingEmitter(); |
| ServiceEmitter serviceEmitter = new ServiceEmitter("", "", cachingEmitter); |
| DefaultQueryMetrics<Query<?>> queryMetrics = new DefaultQueryMetrics<>(); |
| testQueryMetricsDefaultMetricNamesAndUnits(cachingEmitter, serviceEmitter, queryMetrics); |
| } |
| |
| public static void testQueryMetricsDefaultMetricNamesAndUnits( |
| CachingEmitter cachingEmitter, |
| ServiceEmitter serviceEmitter, |
| QueryMetrics<? extends Query<?>> queryMetrics |
| ) |
| { |
| queryMetrics.reportQueryTime(1000001).emit(serviceEmitter); |
| Map<String, Object> actualEvent = cachingEmitter.getLastEmittedEvent().toMap(); |
| Assert.assertEquals("query/time", actualEvent.get("metric")); |
| // query/time and most metrics below are measured in milliseconds by default |
| Assert.assertEquals(1L, actualEvent.get("value")); |
| |
| queryMetrics.reportWaitTime(2000001).emit(serviceEmitter); |
| actualEvent = cachingEmitter.getLastEmittedEvent().toMap(); |
| Assert.assertEquals("query/wait/time", actualEvent.get("metric")); |
| Assert.assertEquals(2L, actualEvent.get("value")); |
| |
| queryMetrics.reportSegmentTime(3000001).emit(serviceEmitter); |
| actualEvent = cachingEmitter.getLastEmittedEvent().toMap(); |
| Assert.assertEquals("query/segment/time", actualEvent.get("metric")); |
| Assert.assertEquals(3L, actualEvent.get("value")); |
| |
| queryMetrics.reportSegmentAndCacheTime(4000001).emit(serviceEmitter); |
| actualEvent = cachingEmitter.getLastEmittedEvent().toMap(); |
| Assert.assertEquals("query/segmentAndCache/time", actualEvent.get("metric")); |
| Assert.assertEquals(4L, actualEvent.get("value")); |
| |
| queryMetrics.reportCpuTime(6000001).emit(serviceEmitter); |
| actualEvent = cachingEmitter.getLastEmittedEvent().toMap(); |
| Assert.assertEquals("query/cpu/time", actualEvent.get("metric")); |
| // CPU time is measured in microseconds by default |
| Assert.assertEquals(6000L, actualEvent.get("value")); |
| |
| queryMetrics.reportNodeTimeToFirstByte(7000001).emit(serviceEmitter); |
| actualEvent = cachingEmitter.getLastEmittedEvent().toMap(); |
| Assert.assertEquals("query/node/ttfb", actualEvent.get("metric")); |
| Assert.assertEquals(7L, actualEvent.get("value")); |
| |
| queryMetrics.reportNodeTime(8000001).emit(serviceEmitter); |
| actualEvent = cachingEmitter.getLastEmittedEvent().toMap(); |
| Assert.assertEquals("query/node/time", actualEvent.get("metric")); |
| Assert.assertEquals(8L, actualEvent.get("value")); |
| |
| queryMetrics.reportQueryBytes(9).emit(serviceEmitter); |
| actualEvent = cachingEmitter.getLastEmittedEvent().toMap(); |
| Assert.assertEquals("query/bytes", actualEvent.get("metric")); |
| Assert.assertEquals(9L, actualEvent.get("value")); |
| |
| queryMetrics.reportNodeBytes(10).emit(serviceEmitter); |
| actualEvent = cachingEmitter.getLastEmittedEvent().toMap(); |
| Assert.assertEquals("query/node/bytes", actualEvent.get("metric")); |
| Assert.assertEquals(10L, actualEvent.get("value")); |
| |
| // Here we are testing that Queried Segment Count does not get emitted by the DefaultQueryMetrics and the last |
| // metric remains as query/node/bytes |
| queryMetrics.reportQueriedSegmentCount(25).emit(serviceEmitter); |
| actualEvent = cachingEmitter.getLastEmittedEvent().toMap(); |
| Assert.assertEquals("query/node/bytes", actualEvent.get("metric")); |
| Assert.assertEquals(10L, actualEvent.get("value")); |
| } |
| } |