SOLR-9026: add facet telemetry for legacy facets

This commit is contained in:
yonik 2016-05-07 18:47:01 -04:00
parent 30cbab6793
commit b42945ea92
6 changed files with 104 additions and 31 deletions

View File

@ -126,6 +126,10 @@ New Features
* SOLR-8972: Add GraphHandler and GraphMLResponseWriter to support graph visualizations (Joel Bernstein)
* SOLR-9026: Extend facet telemetry support to legacy (non-json) facets under "debug/facet-debug" in
the response. (Michael Sun, yonik)
Bug Fixes
----------------------

View File

@ -114,6 +114,11 @@ public class DebugComponent extends SearchComponent
if (fdebug != null) {
info.add("facet-trace", fdebug.getFacetDebugInfo());
}
fdebug = (FacetDebugInfo)(rb.req.getContext().get("FacetDebugInfo-nonJson"));
if (fdebug != null) {
info.add("facet-debug", fdebug.getFacetDebugInfo());
}
if (rb.req.getJSON() != null) {
info.add(JSON, rb.req.getJSON());

View File

@ -22,7 +22,6 @@ import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@ -50,6 +49,8 @@ import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.schema.FieldType;
import org.apache.solr.search.QueryParsing;
import org.apache.solr.search.SyntaxError;
import org.apache.solr.search.facet.FacetDebugInfo;
import org.apache.solr.util.RTimer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -252,7 +253,16 @@ public class FacetComponent extends SearchComponent {
SolrParams params = rb.req.getParams();
SimpleFacets f = new SimpleFacets(rb.req, rb.getResults().docSet, params, rb);
NamedList<Object> counts = FacetComponent.getFacetCounts(f);
RTimer timer = null;
FacetDebugInfo fdebug = null;
if (rb.isDebug()) {
fdebug = new FacetDebugInfo();
rb.req.getContext().put("FacetDebugInfo-nonJson", fdebug);
timer = new RTimer();
}
NamedList<Object> counts = FacetComponent.getFacetCounts(f, fdebug);
String[] pivots = params.getParams(FacetParams.FACET_PIVOT);
if (!ArrayUtils.isEmpty(pivots)) {
PivotFacetProcessor pivotProcessor
@ -264,10 +274,19 @@ public class FacetComponent extends SearchComponent {
}
}
if (fdebug != null) {
long timeElapsed = (long) timer.getTime();
fdebug.setElapse(timeElapsed);
}
rb.rsp.add("facet_counts", counts);
}
}
public static NamedList<Object> getFacetCounts(SimpleFacets simpleFacets) {
return getFacetCounts(simpleFacets, null);
}
/**
* Looks at various Params to determining if any simple Facet Constraint count
* computations are desired.
@ -279,7 +298,7 @@ public class FacetComponent extends SearchComponent {
* @see FacetParams#FACET
* @return a NamedList of Facet Count info or null
*/
public static NamedList<Object> getFacetCounts(SimpleFacets simpleFacets) {
public static NamedList<Object> getFacetCounts(SimpleFacets simpleFacets, FacetDebugInfo fdebug) {
// if someone called this method, benefit of the doubt: assume true
if (!simpleFacets.getGlobalParams().getBool(FacetParams.FACET, true))
return null;
@ -288,7 +307,19 @@ public class FacetComponent extends SearchComponent {
NamedList<Object> counts = new SimpleOrderedMap<>();
try {
counts.add(FACET_QUERY_KEY, simpleFacets.getFacetQueryCounts());
counts.add(FACET_FIELD_KEY, simpleFacets.getFacetFieldCounts());
if (fdebug != null) {
FacetDebugInfo fd = new FacetDebugInfo();
fd.putInfoItem("action", "field facet");
fd.setProcessor(simpleFacets.getClass().getSimpleName());
fdebug.addChild(fd);
simpleFacets.setFacetDebugInfo(fd);
final RTimer timer = new RTimer();
counts.add(FACET_FIELD_KEY, simpleFacets.getFacetFieldCounts());
long timeElapsed = (long) timer.getTime();
fd.setElapse(timeElapsed);
} else {
counts.add(FACET_FIELD_KEY, simpleFacets.getFacetFieldCounts());
}
counts.add(FACET_RANGES_KEY, rangeFacetProcessor.getFacetRangeCounts());
counts.add(FACET_INTERVALS_KEY, simpleFacets.getFacetIntervalCounts());
counts.add(SpatialHeatmapFacets.RESPONSE_KEY, simpleFacets.getHeatmapCounts());

View File

@ -16,6 +16,9 @@
*/
package org.apache.solr.request;
import java.io.IOException;
import java.util.List;
import org.apache.lucene.index.DocValues;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.MultiDocValues.MultiSortedDocValues;
@ -37,11 +40,9 @@ import org.apache.solr.schema.SchemaField;
import org.apache.solr.search.DocSet;
import org.apache.solr.search.Filter;
import org.apache.solr.search.SolrIndexSearcher;
import org.apache.solr.search.facet.FacetDebugInfo;
import org.apache.solr.util.LongPriorityQueue;
import java.io.IOException;
import java.util.List;
/**
* Computes term facets for docvalues field (single or multivalued).
* <p>
@ -57,7 +58,7 @@ import java.util.List;
public class DocValuesFacets {
private DocValuesFacets() {}
public static NamedList<Integer> getCounts(SolrIndexSearcher searcher, DocSet docs, String fieldName, int offset, int limit, int mincount, boolean missing, String sort, String prefix, String contains, boolean ignoreCase) throws IOException {
public static NamedList<Integer> getCounts(SolrIndexSearcher searcher, DocSet docs, String fieldName, int offset, int limit, int mincount, boolean missing, String sort, String prefix, String contains, boolean ignoreCase, FacetDebugInfo fdebug) throws IOException {
SchemaField schemaField = searcher.getSchema().getField(fieldName);
FieldType ft = schemaField.getType();
NamedList<Integer> res = new NamedList<>();
@ -118,6 +119,9 @@ public class DocValuesFacets {
// count collection array only needs to be as big as the number of terms we are
// going to collect counts for.
final int[] counts = new int[nTerms];
if (fdebug != null) {
fdebug.putInfoItem("numBuckets", nTerms);
}
Filter filter = docs.getTopFilter();
List<LeafReaderContext> leaves = searcher.getTopReaderContext().leaves();

View File

@ -16,6 +16,24 @@
*/
package org.apache.solr.request;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.RunnableFuture;
import java.util.concurrent.Semaphore;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang.StringUtils;
import org.apache.lucene.index.Fields;
import org.apache.lucene.index.LeafReader;
@ -49,7 +67,6 @@ import org.apache.solr.common.util.ExecutorUtil;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.common.util.StrUtils;
import org.apache.solr.handler.component.FacetComponent;
import org.apache.solr.handler.component.ResponseBuilder;
import org.apache.solr.handler.component.SpatialHeatmapFacets;
import org.apache.solr.request.IntervalFacets.FacetInterval;
@ -69,28 +86,12 @@ import org.apache.solr.search.QueryParsing;
import org.apache.solr.search.SolrIndexSearcher;
import org.apache.solr.search.SortedIntDocSet;
import org.apache.solr.search.SyntaxError;
import org.apache.solr.search.facet.FacetDebugInfo;
import org.apache.solr.search.facet.FacetProcessor;
import org.apache.solr.search.grouping.GroupingSpecification;
import org.apache.solr.util.BoundedTreeSet;
import org.apache.solr.util.DefaultSolrThreadFactory;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.RunnableFuture;
import java.util.concurrent.Semaphore;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
import org.apache.solr.util.RTimer;
/**
* A class that generates simple Facet information for a request.
@ -109,6 +110,9 @@ public class SimpleFacets {
protected final SolrQueryRequest req;
protected final ResponseBuilder rb;
protected FacetDebugInfo fdebugParent;
protected FacetDebugInfo fdebug;
// per-facet values
protected final static class ParsedParams {
final public SolrParams localParams; // localParams on this particular facet command
@ -160,6 +164,10 @@ public class SimpleFacets {
this.rb = rb;
}
public void setFacetDebugInfo(FacetDebugInfo fdebugParent) {
this.fdebugParent = fdebugParent;
}
/**
* Returns <code>true</code> if a String contains the given substring. Otherwise
* <code>false</code>.
@ -450,6 +458,14 @@ public class SimpleFacets {
method = FacetMethod.FC;
}
RTimer timer = null;
if (fdebug != null) {
fdebug.putInfoItem("method", method.name());
fdebug.putInfoItem("inputDocSetSize", docs.size());
fdebug.putInfoItem("field", field);
timer = new RTimer();
}
if (params.getFieldBool(field, GroupParams.GROUP_FACET, false)) {
counts = getGroupedCounts(searcher, docs, field, multiToken, offset,limit, mincount, missing, sort, prefix, contains, ignoreCase);
} else {
@ -535,13 +551,18 @@ public class SimpleFacets {
}
break;
case FC:
counts = DocValuesFacets.getCounts(searcher, docs, field, offset,limit, mincount, missing, sort, prefix, contains, ignoreCase);
counts = DocValuesFacets.getCounts(searcher, docs, field, offset,limit, mincount, missing, sort, prefix, contains, ignoreCase, fdebug);
break;
default:
throw new AssertionError();
}
}
if (fdebug != null) {
long timeElapsed = (long) timer.getTime();
fdebug.setElapse(timeElapsed);
}
return counts;
}
@ -654,9 +675,17 @@ public class SimpleFacets {
final Semaphore semaphore = new Semaphore((maxThreads <= 0) ? Integer.MAX_VALUE : maxThreads);
List<Future<NamedList>> futures = new ArrayList<>(facetFs.length);
if (fdebugParent != null) {
fdebugParent.putInfoItem("maxThreads", maxThreads);
}
try {
//Loop over fields; submit to executor, keeping the future
for (String f : facetFs) {
if (fdebugParent != null) {
fdebug = new FacetDebugInfo();
fdebugParent.addChild(fdebug);
}
final ParsedParams parsed = parseParams(FacetParams.FACET_FIELD, f);
final SolrParams localParams = parsed.localParams;
final String termList = localParams == null ? null : localParams.get(CommonParams.TERMS);

View File

@ -25,7 +25,7 @@ import org.apache.solr.common.util.SimpleOrderedMap;
public class FacetDebugInfo {
String processor;
long elapse;
long elapse = -1;
String filter;
Map<String, Object> info; // additional information
final List<FacetDebugInfo> children;
@ -69,8 +69,8 @@ public class FacetDebugInfo {
SimpleOrderedMap<Object> info = new SimpleOrderedMap<>();
if (filter != null) info.add("filter", filter);
info.add("processor", processor);
info.add("elapse", elapse);
if (processor != null) info.add("processor", processor);
if (elapse != -1) info.add("elapse", elapse);
if (reqDescription != null) {
info.addAll(reqDescription);
}