mirror of https://github.com/apache/druid.git
granularity method in QueryMetrics. (#4570)
* granularity method in QueryMetrics. PR to emit granularity dimension for timeseries, search, groupBy, select and topN queries. * QueryMetricsFactory classes for search and select queries. * Empty implementation for Granularity() method. * Review comment changes. * Remove unused import. * empty query() method. * checkstyle fix. * Import fix.
This commit is contained in:
parent
07aa405a6f
commit
2ee32399ff
|
@ -22,6 +22,7 @@ package io.druid.query;
|
|||
import com.metamx.emitter.service.ServiceEmitter;
|
||||
import io.druid.collections.bitmap.BitmapFactory;
|
||||
import io.druid.query.filter.Filter;
|
||||
import io.druid.query.search.SearchQueryMetricsFactory;
|
||||
import org.joda.time.Interval;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -110,30 +111,35 @@ import java.util.List;
|
|||
*
|
||||
* Making subinterfaces of QueryMetrics for emitting custom dimensions and/or metrics for specific query types
|
||||
* -----------------------------------------------------------------------------------------------------------
|
||||
* If a query type (e. g. {@link io.druid.query.search.SearchQuery} (it's runners) needs to emit custom
|
||||
* dimensions and/or metrics which doesn't make sense for all other query types, the following steps should be executed:
|
||||
* 1. Create `interface SearchQueryMetrics extends QueryMetrics` (here and below "Search" is the query type) with
|
||||
* additional methods (see "Adding new methods" section above).
|
||||
* If a query type (e. g. {@link io.druid.query.metadata.metadata.SegmentMetadataQuery} (it's runners) needs to emit
|
||||
* custom dimensions and/or metrics which doesn't make sense for all other query types, the following steps should be
|
||||
* executed:
|
||||
*
|
||||
* 2. Create `class DefaultSearchQueryMetrics implements SearchQueryMetrics`. This class should implement extra methods
|
||||
* from SearchQueryMetrics interfaces with empty bodies, AND DELEGATE ALL OTHER METHODS TO A QueryMetrics OBJECT,
|
||||
* provided as a sole parameter in DefaultSearchQueryMetrics constructor.
|
||||
* 1. Create `interface SegmentMetadataQueryMetrics extends QueryMetrics` (here and below "SegmentMetadata" is the
|
||||
* query type) with additional methods (see "Adding new methods" section above).
|
||||
*
|
||||
* 3. Create `interface SearchQueryMetricsFactory` with a single method
|
||||
* `SearchQueryMetrics makeMetrics(SearchQuery query);`.
|
||||
* 2. Create `class DefaultSegmentMetadataQueryMetrics implements SegmentMetadataQueryMetrics`. This class should
|
||||
* implement extra methods from SegmentMetadataQueryMetrics interfaces with empty bodies, AND DELEGATE ALL OTHER
|
||||
* METHODS TO A QueryMetrics OBJECT, provided as a sole parameter in DefaultSegmentMetadataQueryMetrics constructor.
|
||||
*
|
||||
* 4. Create `class DefaultSearchQueryMetricsFactory implements SearchQueryMetricsFactory`, which accepts {@link
|
||||
* GenericQueryMetricsFactory} as injected constructor parameter, and implements makeMetrics() as
|
||||
* `return new DefaultSearchQueryMetrics(genericQueryMetricsFactory.makeMetrics(query));`
|
||||
* NOTE: query(), dataSource(), queryType(), interval(), hasFilters(), duration() and queryId() methods or any
|
||||
* "pre-query-execution-time" methods should either have a empty body or throw exception.
|
||||
*
|
||||
* 5. Inject and use SearchQueryMetricsFactory instead of {@link GenericQueryMetricsFactory} in {@link
|
||||
* io.druid.query.search.SearchQueryQueryToolChest}.
|
||||
* 3. Create `interface SegmentMetadataQueryMetricsFactory` with a single method
|
||||
* `SegmentMetadataQueryMetrics makeMetrics(SegmentMetadataQuery query);`.
|
||||
*
|
||||
* 6. Establish injection of SearchQueryMetricsFactory using config and provider method in QueryToolChestModule
|
||||
* (see how it is done in QueryToolChestModule for existing query types with custom metrics, e. g. {@link
|
||||
* io.druid.query.topn.TopNQueryMetricsFactory}), if the query type belongs to the core druid-processing, e. g.
|
||||
* SearchQuery. If the query type defined in an extension, you can specify
|
||||
* `binder.bind(ScanQueryMetricsFactory.class).to(DefaultScanQueryMetricsFactory.class)` in the extension's
|
||||
* 4. Create `class DefaultSegmentMetadataQueryMetricsFactory implements SegmentMetadataQueryMetricsFactory`,
|
||||
* which accepts {@link GenericQueryMetricsFactory} as injected constructor parameter, and implements makeMetrics() as
|
||||
* `return new DefaultSegmentMetadataQueryMetrics(genericQueryMetricsFactory.makeMetrics(query));`
|
||||
*
|
||||
* 5. Inject and use SegmentMetadataQueryMetricsFactory instead of {@link GenericQueryMetricsFactory} in
|
||||
* {@link io.druid.query.metadata.SegmentMetadataQueryQueryToolChest}.
|
||||
*
|
||||
* 6. Establish injection of SegmentMetadataQueryMetricsFactory using config and provider method in
|
||||
* QueryToolChestModule (see how it is done in {@link io.druid.guice.QueryToolChestModule} for existing query types
|
||||
* with custom metrics, e. g. {@link SearchQueryMetricsFactory}), if the query type
|
||||
* belongs to the core druid-processing, e. g. SegmentMetadataQuery. If the query type defined in an extension, you
|
||||
* can specify `binder.bind(ScanQueryMetricsFactory.class).to(DefaultScanQueryMetricsFactory.class)` in the extension's
|
||||
* Guice module, if the query type is defined in an extension, e. g. ScanQuery. Or establish similar configuration,
|
||||
* as for the core query types.
|
||||
*
|
||||
|
@ -146,6 +152,9 @@ import java.util.List;
|
|||
* dimensions than the default generic QueryMetrics. So those subinterfaces shouldn't be taken as direct examples for
|
||||
* following the plan specified above.
|
||||
*
|
||||
* Refer {@link SearchQueryMetricsFactory}
|
||||
* and {@link io.druid.query.select.SelectQueryMetricsFactory} as an implementation example of this procedure.
|
||||
*
|
||||
* @param <QueryType>
|
||||
*/
|
||||
public interface QueryMetrics<QueryType extends Query<?>>
|
||||
|
|
|
@ -38,6 +38,7 @@ public class DefaultGroupByQueryMetrics extends DefaultQueryMetrics<GroupByQuery
|
|||
numDimensions(query);
|
||||
numMetrics(query);
|
||||
numComplexMetrics(query);
|
||||
granularity(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -58,4 +59,10 @@ public class DefaultGroupByQueryMetrics extends DefaultQueryMetrics<GroupByQuery
|
|||
int numComplexAggs = DruidMetrics.findNumComplexAggs(query.getAggregatorSpecs());
|
||||
setDimension("numComplexMetrics", String.valueOf(numComplexAggs));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void granularity(GroupByQuery query)
|
||||
{
|
||||
//Don't emit by default
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,4 +42,9 @@ public interface GroupByQueryMetrics extends QueryMetrics<GroupByQuery>
|
|||
* method.
|
||||
*/
|
||||
void numComplexMetrics(GroupByQuery query);
|
||||
|
||||
/**
|
||||
* Sets the granularity of {@link GroupByQuery#getGranularity()} of the given query as dimension.
|
||||
*/
|
||||
void granularity(GroupByQuery query);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,240 @@
|
|||
/*
|
||||
* Licensed to Metamarkets Group Inc. (Metamarkets) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. Metamarkets 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 io.druid.query.search;
|
||||
|
||||
import com.metamx.emitter.service.ServiceEmitter;
|
||||
import io.druid.collections.bitmap.BitmapFactory;
|
||||
import io.druid.java.util.common.ISE;
|
||||
import io.druid.query.BitmapResultFactory;
|
||||
import io.druid.query.Query;
|
||||
import io.druid.query.QueryMetrics;
|
||||
import io.druid.query.filter.Filter;
|
||||
import org.joda.time.Interval;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class is implemented with delegation to another QueryMetrics for compatibility, see "Making subinterfaces of
|
||||
* QueryMetrics for emitting custom dimensions and/or metrics for specific query types" section in {@link QueryMetrics}
|
||||
* javadoc.
|
||||
*/
|
||||
public class DefaultSearchQueryMetrics implements SearchQueryMetrics
|
||||
{
|
||||
private QueryMetrics<Query<?>> delegateQueryMetrics;
|
||||
|
||||
|
||||
// queryMetrics.query(query) must already be called on the provided queryMetrics.
|
||||
public DefaultSearchQueryMetrics(QueryMetrics<Query<?>> queryMetrics)
|
||||
{
|
||||
this.delegateQueryMetrics = queryMetrics;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void query(SearchQuery query)
|
||||
{
|
||||
//delegateQueryMetrics.query(query) must already be called on the provided queryMetrics.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dataSource(SearchQuery query)
|
||||
{
|
||||
throw new ISE("Unsupported method in default query metrics implementation.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queryType(SearchQuery query)
|
||||
{
|
||||
throw new ISE("Unsupported method in default query metrics implementation.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interval(SearchQuery query)
|
||||
{
|
||||
throw new ISE("Unsupported method in default query metrics implementation.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hasFilters(SearchQuery query)
|
||||
{
|
||||
throw new ISE("Unsupported method in default query metrics implementation.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void duration(SearchQuery query)
|
||||
{
|
||||
throw new ISE("Unsupported method in default query metrics implementation.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queryId(SearchQuery query)
|
||||
{
|
||||
throw new ISE("Unsupported method in default query metrics implementation.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void granularity(SearchQuery query)
|
||||
{
|
||||
// Don't emit by default
|
||||
}
|
||||
|
||||
@Override
|
||||
public void context(SearchQuery query)
|
||||
{
|
||||
delegateQueryMetrics.context(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void server(String host)
|
||||
{
|
||||
delegateQueryMetrics.server(host);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remoteAddress(String remoteAddress)
|
||||
{
|
||||
delegateQueryMetrics.remoteAddress(remoteAddress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void status(String status)
|
||||
{
|
||||
delegateQueryMetrics.status(status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void success(boolean success)
|
||||
{
|
||||
delegateQueryMetrics.success(success);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void segment(String segmentIdentifier)
|
||||
{
|
||||
delegateQueryMetrics.segment(segmentIdentifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void chunkInterval(Interval interval)
|
||||
{
|
||||
delegateQueryMetrics.chunkInterval(interval);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preFilters(List<Filter> preFilters)
|
||||
{
|
||||
delegateQueryMetrics.preFilters(preFilters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postFilters(List<Filter> postFilters)
|
||||
{
|
||||
delegateQueryMetrics.postFilters(postFilters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BitmapResultFactory<?> makeBitmapResultFactory(BitmapFactory factory)
|
||||
{
|
||||
return delegateQueryMetrics.makeBitmapResultFactory(factory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryMetrics reportQueryTime(long timeNs)
|
||||
{
|
||||
return delegateQueryMetrics.reportQueryTime(timeNs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryMetrics reportQueryBytes(long byteCount)
|
||||
{
|
||||
return delegateQueryMetrics.reportQueryBytes(byteCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryMetrics reportWaitTime(long timeNs)
|
||||
{
|
||||
return delegateQueryMetrics.reportWaitTime(timeNs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryMetrics reportSegmentTime(long timeNs)
|
||||
{
|
||||
return delegateQueryMetrics.reportSegmentTime(timeNs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryMetrics reportSegmentAndCacheTime(long timeNs)
|
||||
{
|
||||
return delegateQueryMetrics.reportSegmentAndCacheTime(timeNs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryMetrics reportIntervalChunkTime(long timeNs)
|
||||
{
|
||||
return delegateQueryMetrics.reportIntervalChunkTime(timeNs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryMetrics reportCpuTime(long timeNs)
|
||||
{
|
||||
return delegateQueryMetrics.reportCpuTime(timeNs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryMetrics reportNodeTimeToFirstByte(long timeNs)
|
||||
{
|
||||
return delegateQueryMetrics.reportNodeTimeToFirstByte(timeNs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryMetrics reportNodeTime(long timeNs)
|
||||
{
|
||||
return delegateQueryMetrics.reportNodeTime(timeNs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryMetrics reportNodeBytes(long byteCount)
|
||||
{
|
||||
return delegateQueryMetrics.reportNodeBytes(byteCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryMetrics reportBitmapConstructionTime(long timeNs)
|
||||
{
|
||||
return delegateQueryMetrics.reportBitmapConstructionTime(timeNs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryMetrics reportSegmentRows(long numRows)
|
||||
{
|
||||
return delegateQueryMetrics.reportSegmentRows(numRows);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryMetrics reportPreFilteredRows(long numRows)
|
||||
{
|
||||
return delegateQueryMetrics.reportPreFilteredRows(numRows);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emit(ServiceEmitter emitter)
|
||||
{
|
||||
delegateQueryMetrics.emit(emitter);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Licensed to Metamarkets Group Inc. (Metamarkets) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. Metamarkets 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 io.druid.query.search;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.inject.Inject;
|
||||
import io.druid.query.DefaultGenericQueryMetricsFactory;
|
||||
import io.druid.query.GenericQueryMetricsFactory;
|
||||
|
||||
public class DefaultSearchQueryMetricsFactory implements SearchQueryMetricsFactory
|
||||
{
|
||||
private static final SearchQueryMetricsFactory INSTANCE =
|
||||
new DefaultSearchQueryMetricsFactory(DefaultGenericQueryMetricsFactory.instance());
|
||||
private final GenericQueryMetricsFactory genericQueryMetricsFactory;
|
||||
|
||||
@Inject
|
||||
public DefaultSearchQueryMetricsFactory(GenericQueryMetricsFactory genericQueryMetricsFactory)
|
||||
{
|
||||
this.genericQueryMetricsFactory = genericQueryMetricsFactory;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public static SearchQueryMetricsFactory instance()
|
||||
{
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SearchQueryMetrics makeMetrics(SearchQuery query)
|
||||
{
|
||||
return new DefaultSearchQueryMetrics(genericQueryMetricsFactory.makeMetrics(query));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Licensed to Metamarkets Group Inc. (Metamarkets) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. Metamarkets 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 io.druid.query.search;
|
||||
|
||||
import io.druid.query.QueryMetrics;
|
||||
|
||||
public interface SearchQueryMetrics extends QueryMetrics<SearchQuery>
|
||||
{
|
||||
/**
|
||||
* Sets the granularity of {@link SearchQuery#getGranularity()} of the given query as dimension.
|
||||
*/
|
||||
void granularity(SearchQuery query);
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Licensed to Metamarkets Group Inc. (Metamarkets) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. Metamarkets 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 io.druid.query.search;
|
||||
|
||||
/**
|
||||
* Implementations could be injected using
|
||||
*
|
||||
* PolyBind
|
||||
* .optionBinder(binder, Key.get(SearchQueryMetricsFactory.class))
|
||||
* .addBinding("myCustomSearchQueryMetricsFactory")
|
||||
* .to(MyCustomSearchQueryMetricsFactory.class);
|
||||
*
|
||||
* And then setting property:
|
||||
* druid.query.search.queryMetricsFactory=myCustomSearchQueryMetricsFactory
|
||||
*/
|
||||
public interface SearchQueryMetricsFactory
|
||||
{
|
||||
SearchQueryMetrics makeMetrics(SearchQuery searchQuery);
|
||||
}
|
|
@ -37,12 +37,9 @@ import io.druid.java.util.common.guava.Sequence;
|
|||
import io.druid.java.util.common.guava.Sequences;
|
||||
import io.druid.java.util.common.guava.nary.BinaryFn;
|
||||
import io.druid.query.CacheStrategy;
|
||||
import io.druid.query.DefaultGenericQueryMetricsFactory;
|
||||
import io.druid.query.GenericQueryMetricsFactory;
|
||||
import io.druid.query.IntervalChunkingQueryRunnerDecorator;
|
||||
import io.druid.query.Query;
|
||||
import io.druid.query.QueryContexts;
|
||||
import io.druid.query.QueryMetrics;
|
||||
import io.druid.query.QueryPlus;
|
||||
import io.druid.query.QueryRunner;
|
||||
import io.druid.query.QueryToolChest;
|
||||
|
@ -73,7 +70,7 @@ public class SearchQueryQueryToolChest extends QueryToolChest<Result<SearchResul
|
|||
|
||||
private final SearchQueryConfig config;
|
||||
private final IntervalChunkingQueryRunnerDecorator intervalChunkingQueryRunnerDecorator;
|
||||
private final GenericQueryMetricsFactory queryMetricsFactory;
|
||||
private final SearchQueryMetricsFactory queryMetricsFactory;
|
||||
|
||||
@VisibleForTesting
|
||||
public SearchQueryQueryToolChest(
|
||||
|
@ -81,14 +78,14 @@ public class SearchQueryQueryToolChest extends QueryToolChest<Result<SearchResul
|
|||
IntervalChunkingQueryRunnerDecorator intervalChunkingQueryRunnerDecorator
|
||||
)
|
||||
{
|
||||
this(config, intervalChunkingQueryRunnerDecorator, DefaultGenericQueryMetricsFactory.instance());
|
||||
this(config, intervalChunkingQueryRunnerDecorator, DefaultSearchQueryMetricsFactory.instance());
|
||||
}
|
||||
|
||||
@Inject
|
||||
public SearchQueryQueryToolChest(
|
||||
SearchQueryConfig config,
|
||||
IntervalChunkingQueryRunnerDecorator intervalChunkingQueryRunnerDecorator,
|
||||
GenericQueryMetricsFactory queryMetricsFactory
|
||||
SearchQueryMetricsFactory queryMetricsFactory
|
||||
)
|
||||
{
|
||||
this.config = config;
|
||||
|
@ -124,9 +121,11 @@ public class SearchQueryQueryToolChest extends QueryToolChest<Result<SearchResul
|
|||
}
|
||||
|
||||
@Override
|
||||
public QueryMetrics<Query<?>> makeMetrics(SearchQuery query)
|
||||
public SearchQueryMetrics makeMetrics(SearchQuery query)
|
||||
{
|
||||
return queryMetricsFactory.makeMetrics(query);
|
||||
SearchQueryMetrics metrics = queryMetricsFactory.makeMetrics(query);
|
||||
metrics.query(query);
|
||||
return metrics;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,239 @@
|
|||
/*
|
||||
* Licensed to Metamarkets Group Inc. (Metamarkets) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. Metamarkets 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 io.druid.query.select;
|
||||
|
||||
import com.metamx.emitter.service.ServiceEmitter;
|
||||
import io.druid.collections.bitmap.BitmapFactory;
|
||||
import io.druid.java.util.common.ISE;
|
||||
import io.druid.query.BitmapResultFactory;
|
||||
import io.druid.query.Query;
|
||||
import io.druid.query.QueryMetrics;
|
||||
import io.druid.query.filter.Filter;
|
||||
import org.joda.time.Interval;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class is implemented with delegation to another QueryMetrics for compatibility, see "Making subinterfaces of
|
||||
* QueryMetrics for emitting custom dimensions and/or metrics for specific query types" section in {@link QueryMetrics}
|
||||
* javadoc.
|
||||
*/
|
||||
public class DefaultSelectQueryMetrics implements SelectQueryMetrics
|
||||
{
|
||||
private QueryMetrics<Query<?>> delegateQueryMetrics;
|
||||
|
||||
// queryMetrics.query(query) must already be called on the provided queryMetrics.
|
||||
public DefaultSelectQueryMetrics(QueryMetrics<Query<?>> queryMetrics)
|
||||
{
|
||||
this.delegateQueryMetrics = queryMetrics;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void query(SelectQuery query)
|
||||
{
|
||||
// delegateQueryMetrics.query(query) must already be called on the provided queryMetrics.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dataSource(SelectQuery query)
|
||||
{
|
||||
throw new ISE("Unsupported method in default query metrics implementation.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queryType(SelectQuery query)
|
||||
{
|
||||
throw new ISE("Unsupported method in default query metrics implementation.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interval(SelectQuery query)
|
||||
{
|
||||
throw new ISE("Unsupported method in default query metrics implementation.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hasFilters(SelectQuery query)
|
||||
{
|
||||
throw new ISE("Unsupported method in default query metrics implementation.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void duration(SelectQuery query)
|
||||
{
|
||||
throw new ISE("Unsupported method in default query metrics implementation.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queryId(SelectQuery query)
|
||||
{
|
||||
throw new ISE("Unsupported method in default query metrics implementation.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void granularity(SelectQuery query)
|
||||
{
|
||||
// Don't emit by default
|
||||
}
|
||||
|
||||
@Override
|
||||
public void context(SelectQuery query)
|
||||
{
|
||||
delegateQueryMetrics.context(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void server(String host)
|
||||
{
|
||||
delegateQueryMetrics.server(host);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remoteAddress(String remoteAddress)
|
||||
{
|
||||
delegateQueryMetrics.remoteAddress(remoteAddress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void status(String status)
|
||||
{
|
||||
delegateQueryMetrics.status(status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void success(boolean success)
|
||||
{
|
||||
delegateQueryMetrics.success(success);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void segment(String segmentIdentifier)
|
||||
{
|
||||
delegateQueryMetrics.segment(segmentIdentifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void chunkInterval(Interval interval)
|
||||
{
|
||||
delegateQueryMetrics.chunkInterval(interval);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preFilters(List<Filter> preFilters)
|
||||
{
|
||||
delegateQueryMetrics.preFilters(preFilters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postFilters(List<Filter> postFilters)
|
||||
{
|
||||
delegateQueryMetrics.postFilters(postFilters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BitmapResultFactory<?> makeBitmapResultFactory(BitmapFactory factory)
|
||||
{
|
||||
return delegateQueryMetrics.makeBitmapResultFactory(factory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryMetrics reportQueryTime(long timeNs)
|
||||
{
|
||||
return delegateQueryMetrics.reportQueryTime(timeNs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryMetrics reportQueryBytes(long byteCount)
|
||||
{
|
||||
return delegateQueryMetrics.reportQueryBytes(byteCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryMetrics reportWaitTime(long timeNs)
|
||||
{
|
||||
return delegateQueryMetrics.reportWaitTime(timeNs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryMetrics reportSegmentTime(long timeNs)
|
||||
{
|
||||
return delegateQueryMetrics.reportSegmentTime(timeNs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryMetrics reportSegmentAndCacheTime(long timeNs)
|
||||
{
|
||||
return delegateQueryMetrics.reportSegmentAndCacheTime(timeNs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryMetrics reportIntervalChunkTime(long timeNs)
|
||||
{
|
||||
return delegateQueryMetrics.reportIntervalChunkTime(timeNs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryMetrics reportCpuTime(long timeNs)
|
||||
{
|
||||
return delegateQueryMetrics.reportCpuTime(timeNs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryMetrics reportNodeTimeToFirstByte(long timeNs)
|
||||
{
|
||||
return delegateQueryMetrics.reportNodeTimeToFirstByte(timeNs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryMetrics reportNodeTime(long timeNs)
|
||||
{
|
||||
return delegateQueryMetrics.reportNodeTime(timeNs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryMetrics reportNodeBytes(long byteCount)
|
||||
{
|
||||
return delegateQueryMetrics.reportNodeBytes(byteCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryMetrics reportBitmapConstructionTime(long timeNs)
|
||||
{
|
||||
return delegateQueryMetrics.reportBitmapConstructionTime(timeNs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryMetrics reportSegmentRows(long numRows)
|
||||
{
|
||||
return delegateQueryMetrics.reportSegmentRows(numRows);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryMetrics reportPreFilteredRows(long numRows)
|
||||
{
|
||||
return delegateQueryMetrics.reportPreFilteredRows(numRows);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emit(ServiceEmitter emitter)
|
||||
{
|
||||
delegateQueryMetrics.emit(emitter);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Licensed to Metamarkets Group Inc. (Metamarkets) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. Metamarkets 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 io.druid.query.select;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.inject.Inject;
|
||||
import io.druid.query.DefaultGenericQueryMetricsFactory;
|
||||
import io.druid.query.GenericQueryMetricsFactory;
|
||||
|
||||
public class DefaultSelectQueryMetricsFactory implements SelectQueryMetricsFactory
|
||||
{
|
||||
private static final SelectQueryMetricsFactory INSTANCE =
|
||||
new DefaultSelectQueryMetricsFactory(DefaultGenericQueryMetricsFactory.instance());
|
||||
|
||||
private final GenericQueryMetricsFactory genericQueryMetricsFactory;
|
||||
|
||||
@Inject
|
||||
public DefaultSelectQueryMetricsFactory(GenericQueryMetricsFactory genericQueryMetricsFactory)
|
||||
{
|
||||
this.genericQueryMetricsFactory = genericQueryMetricsFactory;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public static SelectQueryMetricsFactory instance()
|
||||
{
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SelectQueryMetrics makeMetrics(SelectQuery query)
|
||||
{
|
||||
return new DefaultSelectQueryMetrics(genericQueryMetricsFactory.makeMetrics(query));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Licensed to Metamarkets Group Inc. (Metamarkets) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. Metamarkets 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 io.druid.query.select;
|
||||
|
||||
import io.druid.query.QueryMetrics;
|
||||
|
||||
public interface SelectQueryMetrics extends QueryMetrics<SelectQuery>
|
||||
{
|
||||
/**
|
||||
* Sets the granularity of {@link SelectQuery#getGranularity()} of the given query as dimension.
|
||||
*/
|
||||
void granularity(SelectQuery query);
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Licensed to Metamarkets Group Inc. (Metamarkets) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. Metamarkets 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 io.druid.query.select;
|
||||
|
||||
/**
|
||||
* Implementations could be injected using
|
||||
*
|
||||
* PolyBind
|
||||
* .optionBinder(binder, Key.get(SelectQueryMetricsFactory.class))
|
||||
* .addBinding("myCustomSelectQueryMetricsFactory")
|
||||
* .to(MyCustomSelectQueryMetricsFactory.class);
|
||||
*
|
||||
* And then setting property:
|
||||
* druid.query.select.queryMetricsFactory=myCustomSelectQueryMetricsFactory
|
||||
*/
|
||||
public interface SelectQueryMetricsFactory
|
||||
{
|
||||
SelectQueryMetrics makeMetrics(SelectQuery selectQuery);
|
||||
}
|
|
@ -38,11 +38,8 @@ import io.druid.java.util.common.guava.Comparators;
|
|||
import io.druid.java.util.common.guava.Sequence;
|
||||
import io.druid.java.util.common.guava.nary.BinaryFn;
|
||||
import io.druid.query.CacheStrategy;
|
||||
import io.druid.query.DefaultGenericQueryMetricsFactory;
|
||||
import io.druid.query.GenericQueryMetricsFactory;
|
||||
import io.druid.query.IntervalChunkingQueryRunnerDecorator;
|
||||
import io.druid.query.Query;
|
||||
import io.druid.query.QueryMetrics;
|
||||
import io.druid.query.QueryPlus;
|
||||
import io.druid.query.QueryRunner;
|
||||
import io.druid.query.QueryToolChest;
|
||||
|
@ -83,7 +80,7 @@ public class SelectQueryQueryToolChest extends QueryToolChest<Result<SelectResul
|
|||
private final ObjectMapper jsonMapper;
|
||||
private final IntervalChunkingQueryRunnerDecorator intervalChunkingQueryRunnerDecorator;
|
||||
private final Supplier<SelectQueryConfig> configSupplier;
|
||||
private final GenericQueryMetricsFactory queryMetricsFactory;
|
||||
private final SelectQueryMetricsFactory queryMetricsFactory;
|
||||
|
||||
public SelectQueryQueryToolChest(
|
||||
ObjectMapper jsonMapper,
|
||||
|
@ -91,7 +88,7 @@ public class SelectQueryQueryToolChest extends QueryToolChest<Result<SelectResul
|
|||
Supplier<SelectQueryConfig> configSupplier
|
||||
)
|
||||
{
|
||||
this(jsonMapper, intervalChunkingQueryRunnerDecorator, configSupplier, new DefaultGenericQueryMetricsFactory(jsonMapper));
|
||||
this(jsonMapper, intervalChunkingQueryRunnerDecorator, configSupplier, DefaultSelectQueryMetricsFactory.instance());
|
||||
}
|
||||
|
||||
@Inject
|
||||
|
@ -99,7 +96,7 @@ public class SelectQueryQueryToolChest extends QueryToolChest<Result<SelectResul
|
|||
ObjectMapper jsonMapper,
|
||||
IntervalChunkingQueryRunnerDecorator intervalChunkingQueryRunnerDecorator,
|
||||
Supplier<SelectQueryConfig> configSupplier,
|
||||
GenericQueryMetricsFactory queryMetricsFactory
|
||||
SelectQueryMetricsFactory queryMetricsFactory
|
||||
)
|
||||
{
|
||||
this.jsonMapper = jsonMapper;
|
||||
|
@ -139,9 +136,11 @@ public class SelectQueryQueryToolChest extends QueryToolChest<Result<SelectResul
|
|||
}
|
||||
|
||||
@Override
|
||||
public QueryMetrics<Query<?>> makeMetrics(SelectQuery query)
|
||||
public SelectQueryMetrics makeMetrics(SelectQuery query)
|
||||
{
|
||||
return queryMetricsFactory.makeMetrics(query);
|
||||
SelectQueryMetrics queryMetrics = queryMetricsFactory.makeMetrics(query);
|
||||
queryMetrics.query(query);
|
||||
return queryMetrics;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -37,6 +37,7 @@ public class DefaultTimeseriesQueryMetrics extends DefaultQueryMetrics<Timeserie
|
|||
super.query(query);
|
||||
numMetrics(query);
|
||||
numComplexMetrics(query);
|
||||
granularity(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -51,4 +52,10 @@ public class DefaultTimeseriesQueryMetrics extends DefaultQueryMetrics<Timeserie
|
|||
int numComplexAggs = DruidMetrics.findNumComplexAggs(query.getAggregatorSpecs());
|
||||
setDimension("numComplexMetrics", String.valueOf(numComplexAggs));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void granularity(TimeseriesQuery query)
|
||||
{
|
||||
// Don't emit by default
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,4 +37,9 @@ public interface TimeseriesQueryMetrics extends QueryMetrics<TimeseriesQuery>
|
|||
* method.
|
||||
*/
|
||||
void numComplexMetrics(TimeseriesQuery query);
|
||||
|
||||
/**
|
||||
* Sets the granularity of {@link TimeseriesQuery#getGranularity()} of the given query as dimension.
|
||||
*/
|
||||
void granularity(TimeseriesQuery query);
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ public class DefaultTopNQueryMetrics extends DefaultQueryMetrics<TopNQuery> impl
|
|||
dimension(query);
|
||||
numMetrics(query);
|
||||
numComplexMetrics(query);
|
||||
granularity(query);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -68,6 +69,12 @@ public class DefaultTopNQueryMetrics extends DefaultQueryMetrics<TopNQuery> impl
|
|||
setDimension("numComplexMetrics", String.valueOf(numComplexAggs));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void granularity(TopNQuery query)
|
||||
{
|
||||
// Don't emit by default
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dimensionCardinality(int cardinality)
|
||||
{
|
||||
|
|
|
@ -50,6 +50,11 @@ public interface TopNQueryMetrics extends QueryMetrics<TopNQuery>
|
|||
*/
|
||||
void numComplexMetrics(TopNQuery query);
|
||||
|
||||
/**
|
||||
* Sets the granularity of {@link TopNQuery#getGranularity()} of the given query as dimension.
|
||||
*/
|
||||
void granularity(TopNQuery query);
|
||||
|
||||
void dimensionCardinality(int cardinality);
|
||||
|
||||
void algorithm(TopNAlgorithm algorithm);
|
||||
|
|
|
@ -66,7 +66,6 @@ public class DefaultQueryMetricsTest
|
|||
.filters(new SelectorDimFilter("tags", "t3", null))
|
||||
.build();
|
||||
queryMetrics.query(query);
|
||||
|
||||
queryMetrics.reportQueryTime(0).emit(serviceEmitter);
|
||||
Map<String, Object> actualEvent = cachingEmitter.getLastEmittedEvent().toMap();
|
||||
Assert.assertEquals(12, actualEvent.size());
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Licensed to Metamarkets Group Inc. (Metamarkets) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. Metamarkets 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 io.druid.query.search;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.metamx.emitter.service.ServiceEmitter;
|
||||
import io.druid.query.CachingEmitter;
|
||||
import io.druid.query.DefaultQueryMetricsTest;
|
||||
import io.druid.query.DruidMetrics;
|
||||
import io.druid.query.Druids;
|
||||
import io.druid.query.QueryRunnerTestHelper;
|
||||
import io.druid.query.dimension.DefaultDimensionSpec;
|
||||
import io.druid.query.dimension.ListFilteredDimensionSpec;
|
||||
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 DefaultSearchQueryMetricsTest
|
||||
{
|
||||
|
||||
/**
|
||||
* Tests that passed a query {@link DefaultSearchQueryMetrics} produces events with a certain set of dimensions.
|
||||
*/
|
||||
@Test
|
||||
public void testDefaultSearchQueryMetricsQuery()
|
||||
{
|
||||
CachingEmitter cachingEmitter = new CachingEmitter();
|
||||
ServiceEmitter serviceEmitter = new ServiceEmitter("", "", cachingEmitter);
|
||||
SearchQuery query = Druids
|
||||
.newSearchQueryBuilder()
|
||||
.dataSource(QueryRunnerTestHelper.dataSource)
|
||||
.granularity(QueryRunnerTestHelper.dayGran)
|
||||
.intervals(QueryRunnerTestHelper.fullOnInterval)
|
||||
.dimensions(new ListFilteredDimensionSpec(
|
||||
new DefaultDimensionSpec("tags", "tags"),
|
||||
ImmutableSet.of("t3"),
|
||||
null
|
||||
))
|
||||
.build();
|
||||
|
||||
SearchQueryMetrics queryMetrics = DefaultSearchQueryMetricsFactory.instance().makeMetrics(query);
|
||||
|
||||
queryMetrics.query(query);
|
||||
|
||||
queryMetrics.reportQueryTime(0).emit(serviceEmitter);
|
||||
Map<String, Object> actualEvent = cachingEmitter.getLastEmittedEvent().toMap();
|
||||
Assert.assertEquals(12, actualEvent.size());
|
||||
Assert.assertTrue(actualEvent.containsKey("feed"));
|
||||
Assert.assertTrue(actualEvent.containsKey("timestamp"));
|
||||
Assert.assertEquals("", actualEvent.get("host"));
|
||||
Assert.assertEquals("", actualEvent.get("service"));
|
||||
Assert.assertEquals(QueryRunnerTestHelper.dataSource, actualEvent.get(DruidMetrics.DATASOURCE));
|
||||
Assert.assertEquals(query.getType(), actualEvent.get(DruidMetrics.TYPE));
|
||||
List<Interval> expectedIntervals = QueryRunnerTestHelper.fullOnInterval.getIntervals();
|
||||
List<String> expectedStringIntervals =
|
||||
expectedIntervals.stream().map(Interval::toString).collect(Collectors.toList());
|
||||
Assert.assertEquals(expectedStringIntervals, actualEvent.get(DruidMetrics.INTERVAL));
|
||||
Assert.assertEquals("false", actualEvent.get("hasFilters"));
|
||||
Assert.assertEquals(expectedIntervals.get(0).toDuration().toString(), actualEvent.get("duration"));
|
||||
Assert.assertEquals("", actualEvent.get(DruidMetrics.ID));
|
||||
|
||||
// Metric
|
||||
Assert.assertEquals("query/time", actualEvent.get("metric"));
|
||||
Assert.assertEquals(0L, actualEvent.get("value"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultSearchQueryMetricsMetricNamesAndUnits()
|
||||
{
|
||||
SearchQuery query = Druids
|
||||
.newSearchQueryBuilder()
|
||||
.dataSource(QueryRunnerTestHelper.dataSource)
|
||||
.granularity(QueryRunnerTestHelper.dayGran)
|
||||
.intervals(QueryRunnerTestHelper.fullOnInterval)
|
||||
.build();
|
||||
|
||||
CachingEmitter cachingEmitter = new CachingEmitter();
|
||||
ServiceEmitter serviceEmitter = new ServiceEmitter("", "", cachingEmitter);
|
||||
SearchQueryMetrics queryMetrics = DefaultSearchQueryMetricsFactory.instance().makeMetrics(query);
|
||||
DefaultQueryMetricsTest.testQueryMetricsDefaultMetricNamesAndUnits(cachingEmitter, serviceEmitter, queryMetrics);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Licensed to Metamarkets Group Inc. (Metamarkets) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. Metamarkets 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 io.druid.query.select;
|
||||
|
||||
import com.metamx.emitter.service.ServiceEmitter;
|
||||
import io.druid.query.CachingEmitter;
|
||||
import io.druid.query.DefaultQueryMetricsTest;
|
||||
import io.druid.query.DruidMetrics;
|
||||
import io.druid.query.Druids;
|
||||
import io.druid.query.QueryRunnerTestHelper;
|
||||
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 DefaultSelectQueryMetricsTest
|
||||
{
|
||||
|
||||
/**
|
||||
* Tests that passed a query {@link DefaultSelectQueryMetrics} produces events with a certain set of dimensions.
|
||||
*/
|
||||
@Test
|
||||
public void testDefaultSelectQueryMetricsQuery()
|
||||
{
|
||||
CachingEmitter cachingEmitter = new CachingEmitter();
|
||||
ServiceEmitter serviceEmitter = new ServiceEmitter("", "", cachingEmitter);
|
||||
SelectQuery query = Druids
|
||||
.newSelectQueryBuilder()
|
||||
.dataSource(QueryRunnerTestHelper.dataSource)
|
||||
.granularity(QueryRunnerTestHelper.dayGran)
|
||||
.intervals(QueryRunnerTestHelper.fullOnInterval)
|
||||
.descending(true)
|
||||
.pagingSpec(PagingSpec.newSpec(1))
|
||||
.build();
|
||||
|
||||
SelectQueryMetrics queryMetrics = DefaultSelectQueryMetricsFactory.instance().makeMetrics(query);
|
||||
|
||||
queryMetrics.query(query);
|
||||
|
||||
queryMetrics.reportQueryTime(0).emit(serviceEmitter);
|
||||
Map<String, Object> actualEvent = cachingEmitter.getLastEmittedEvent().toMap();
|
||||
Assert.assertEquals(12, actualEvent.size());
|
||||
Assert.assertTrue(actualEvent.containsKey("feed"));
|
||||
Assert.assertTrue(actualEvent.containsKey("timestamp"));
|
||||
Assert.assertEquals("", actualEvent.get("host"));
|
||||
Assert.assertEquals("", actualEvent.get("service"));
|
||||
Assert.assertEquals(QueryRunnerTestHelper.dataSource, actualEvent.get(DruidMetrics.DATASOURCE));
|
||||
Assert.assertEquals(query.getType(), actualEvent.get(DruidMetrics.TYPE));
|
||||
List<Interval> expectedIntervals = QueryRunnerTestHelper.fullOnInterval.getIntervals();
|
||||
List<String> expectedStringIntervals =
|
||||
expectedIntervals.stream().map(Interval::toString).collect(Collectors.toList());
|
||||
Assert.assertEquals(expectedStringIntervals, actualEvent.get(DruidMetrics.INTERVAL));
|
||||
Assert.assertEquals("false", actualEvent.get("hasFilters"));
|
||||
Assert.assertEquals(expectedIntervals.get(0).toDuration().toString(), actualEvent.get("duration"));
|
||||
Assert.assertEquals("", actualEvent.get(DruidMetrics.ID));
|
||||
|
||||
// Metric
|
||||
Assert.assertEquals("query/time", actualEvent.get("metric"));
|
||||
Assert.assertEquals(0L, actualEvent.get("value"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultSelectQueryMetricsMetricNamesAndUnits()
|
||||
{
|
||||
CachingEmitter cachingEmitter = new CachingEmitter();
|
||||
ServiceEmitter serviceEmitter = new ServiceEmitter("", "", cachingEmitter);
|
||||
SelectQuery query = Druids
|
||||
.newSelectQueryBuilder()
|
||||
.dataSource(QueryRunnerTestHelper.dataSource)
|
||||
.granularity(QueryRunnerTestHelper.dayGran)
|
||||
.intervals(QueryRunnerTestHelper.fullOnInterval)
|
||||
.descending(true)
|
||||
.pagingSpec(PagingSpec.newSpec(1))
|
||||
.build();
|
||||
|
||||
SelectQueryMetrics queryMetrics = DefaultSelectQueryMetricsFactory.instance().makeMetrics(query);
|
||||
DefaultQueryMetricsTest.testQueryMetricsDefaultMetricNamesAndUnits(cachingEmitter, serviceEmitter, queryMetrics);
|
||||
}
|
||||
}
|
|
@ -44,10 +44,14 @@ import io.druid.query.scan.ScanQuery;
|
|||
import io.druid.query.scan.ScanQueryConfig;
|
||||
import io.druid.query.scan.ScanQueryQueryToolChest;
|
||||
import io.druid.query.search.SearchQueryQueryToolChest;
|
||||
import io.druid.query.search.DefaultSearchQueryMetricsFactory;
|
||||
import io.druid.query.search.SearchQuery;
|
||||
import io.druid.query.search.SearchQueryConfig;
|
||||
import io.druid.query.search.SearchQueryMetricsFactory;
|
||||
import io.druid.query.select.DefaultSelectQueryMetricsFactory;
|
||||
import io.druid.query.select.SelectQuery;
|
||||
import io.druid.query.select.SelectQueryConfig;
|
||||
import io.druid.query.select.SelectQueryMetricsFactory;
|
||||
import io.druid.query.select.SelectQueryQueryToolChest;
|
||||
import io.druid.query.timeboundary.TimeBoundaryQuery;
|
||||
import io.druid.query.timeboundary.TimeBoundaryQueryQueryToolChest;
|
||||
|
@ -71,6 +75,8 @@ public class QueryToolChestModule implements Module
|
|||
public static final String GROUPBY_QUERY_METRICS_FACTORY_PROPERTY = "druid.query.groupBy.queryMetricsFactory";
|
||||
public static final String TIMESERIES_QUERY_METRICS_FACTORY_PROPERTY = "druid.query.timeseries.queryMetricsFactory";
|
||||
public static final String TOPN_QUERY_METRICS_FACTORY_PROPERTY = "druid.query.topN.queryMetricsFactory";
|
||||
public static final String SELECT_QUERY_METRICS_FACTORY_PROPERTY = "druid.query.select.queryMetricsFactory";
|
||||
public static final String SEARCH_QUERY_METRICS_FACTORY_PROPERTY = "druid.query.search.queryMetricsFactory";
|
||||
|
||||
public final Map<Class<? extends Query>, Class<? extends QueryToolChest>> mappings =
|
||||
ImmutableMap.<Class<? extends Query>, Class<? extends QueryToolChest>>builder()
|
||||
|
@ -147,5 +153,27 @@ public class QueryToolChestModule implements Module
|
|||
.optionBinder(binder, Key.get(TopNQueryMetricsFactory.class))
|
||||
.addBinding("default")
|
||||
.to(DefaultTopNQueryMetricsFactory.class);
|
||||
|
||||
PolyBind.createChoice(
|
||||
binder,
|
||||
SELECT_QUERY_METRICS_FACTORY_PROPERTY,
|
||||
Key.get(SelectQueryMetricsFactory.class),
|
||||
Key.get(DefaultSelectQueryMetricsFactory.class)
|
||||
);
|
||||
PolyBind
|
||||
.optionBinder(binder, Key.get(SelectQueryMetricsFactory.class))
|
||||
.addBinding("default")
|
||||
.to(DefaultSelectQueryMetricsFactory.class);
|
||||
|
||||
PolyBind.createChoice(
|
||||
binder,
|
||||
SEARCH_QUERY_METRICS_FACTORY_PROPERTY,
|
||||
Key.get(SearchQueryMetricsFactory.class),
|
||||
Key.get(DefaultSearchQueryMetricsFactory.class)
|
||||
);
|
||||
PolyBind
|
||||
.optionBinder(binder, Key.get(SearchQueryMetricsFactory.class))
|
||||
.addBinding("default")
|
||||
.to(DefaultSearchQueryMetricsFactory.class);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue