SOLR-1972: Add extra query stats to RequestHandler

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1403555 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Alan Woodward 2012-10-29 22:13:03 +00:00
parent 7e65097905
commit 03ed8213cb
5 changed files with 71 additions and 21 deletions

View File

@ -55,6 +55,10 @@ New Features
* SOLR-3911: Make Directory and DirectoryFactory first class so that the majority
of Solr's features work with any custom implementations. (Mark Miller)
* SOLR-1972: Add extra statistics to RequestHandlers - 5 & 15-minute reqs/sec
rolling averages; median, 75th, 95th, 99th, 99.9th percentile request times
(Alan Woodward)
Optimizations
----------------------

View File

@ -28,6 +28,7 @@
<dependency org="org.easymock" name="easymock" rev="2.2" transitive="false"/>
<dependency org="com.spatial4j" name="spatial4j" rev="0.3" transitive="false"/>
<dependency org="javax.servlet" name="javax.servlet-api" rev="3.0.1" transitive="false"/>
<dependency org="com.yammer.metrics" name="metrics-core" rev="2.1.2" transitive="false"/>
<exclude org="*" ext="*" matcher="regexp" type="${ivy.exclude.types}"/>
</dependencies>
</ivy-module>

View File

@ -17,6 +17,11 @@
package org.apache.solr.handler;
import com.yammer.metrics.Metrics;
import com.yammer.metrics.core.Counter;
import com.yammer.metrics.core.Timer;
import com.yammer.metrics.core.TimerContext;
import com.yammer.metrics.stats.Snapshot;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.params.SolrParams;
@ -30,26 +35,34 @@ import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.util.SolrPluginUtils;
import java.net.URL;
import java.util.concurrent.atomic.AtomicLong;
/**
*
*/
public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfoMBean {
// statistics
// TODO: should we bother synchronizing these, or is an off-by-one error
// acceptable every million requests or so?
volatile long numRequests;
volatile long numErrors;
volatile long numTimeouts;
protected NamedList initArgs = null;
protected SolrParams defaults;
protected SolrParams appends;
protected SolrParams invariants;
volatile long totalTime = 0;
long handlerStart = System.currentTimeMillis();
protected boolean httpCaching = true;
// Statistics
private static final AtomicLong handlerNumber = new AtomicLong();
private final Counter numRequests;
private final Counter numErrors;
private final Counter numTimeouts;
private final Timer requestTimes;
long handlerStart = System.currentTimeMillis();
public RequestHandlerBase() {
String scope = new String("metrics-scope-" + handlerNumber.getAndIncrement());
numRequests = Metrics.newCounter(RequestHandlerBase.class, "numRequests", scope);
numErrors = Metrics.newCounter(RequestHandlerBase.class, "numErrors", scope);
numTimeouts = Metrics.newCounter(RequestHandlerBase.class, "numTimeouts", scope);
requestTimes = Metrics.newTimer(RequestHandlerBase.class, "requestTimes", scope);
}
/**
* Initializes the {@link org.apache.solr.request.SolrRequestHandler} by creating three {@link org.apache.solr.common.params.SolrParams} named.
@ -93,7 +106,7 @@ public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfo
public void init(NamedList args) {
initArgs = args;
// Copied from StandardRequestHandler
// Copied from StandardRequestHandler
if( args != null ) {
Object o = args.get("defaults");
if (o != null && o instanceof NamedList) {
@ -113,6 +126,7 @@ public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfo
Object caching = initArgs.get("httpCaching");
httpCaching = caching != null ? Boolean.parseBoolean(caching.toString()) : true;
}
}
public NamedList getInitArgs() {
@ -122,7 +136,8 @@ public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfo
public abstract void handleRequestBody( SolrQueryRequest req, SolrQueryResponse rsp ) throws Exception;
public void handleRequest(SolrQueryRequest req, SolrQueryResponse rsp) {
numRequests++;
numRequests.inc();
TimerContext timer = requestTimes.time();
try {
SolrPluginUtils.setDefaults(req,defaults,appends,invariants);
rsp.setHttpCaching(httpCaching);
@ -133,7 +148,7 @@ public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfo
Object partialResults = header.get("partialResults");
boolean timedOut = partialResults == null ? false : (Boolean)partialResults;
if( timedOut ) {
numTimeouts++;
numTimeouts.inc();
rsp.setHttpCaching(false);
}
}
@ -154,11 +169,12 @@ public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfo
}
rsp.setException(e);
numErrors++;
numErrors.inc();
}
finally {
timer.stop();
}
totalTime += rsp.getEndTime() - req.getStartTime();
}
//////////////////////// SolrInfoMBeans methods //////////////////////
@ -184,12 +200,20 @@ public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfo
public NamedList<Object> getStatistics() {
NamedList<Object> lst = new SimpleOrderedMap<Object>();
lst.add("handlerStart",handlerStart);
lst.add("requests", numRequests);
lst.add("errors", numErrors);
lst.add("timeouts", numTimeouts);
lst.add("totalTime",totalTime);
lst.add("avgTimePerRequest", (float) totalTime / (float) this.numRequests);
lst.add("avgRequestsPerSecond", (float) numRequests*1000 / (float)(System.currentTimeMillis()-handlerStart));
lst.add("requests", numRequests.count());
lst.add("errors", numErrors.count());
lst.add("timeouts", numTimeouts.count());
lst.add("totalTime",requestTimes.sum());
lst.add("avgRequestsPerSecond", requestTimes.meanRate());
lst.add("5minRateReqsPerSecond", requestTimes.fiveMinuteRate());
lst.add("15minRateReqsPerSecond", requestTimes.fifteenMinuteRate());
lst.add("avgTimePerRequest", requestTimes.mean());
Snapshot snapshot = requestTimes.getSnapshot();
lst.add("medianRequestTime", snapshot.getMedian());
lst.add("75thPcRequestTime", snapshot.get75thPercentile());
lst.add("95thPcRequestTime", snapshot.get95thPercentile());
lst.add("99thPcRequestTime", snapshot.get99thPercentile());
lst.add("999thPcRequestTime", snapshot.get999thPercentile());
return lst;
}

View File

@ -18,6 +18,7 @@
package org.apache.solr.core;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.handler.StandardRequestHandler;
import org.apache.solr.request.SolrRequestHandler;
import org.junit.BeforeClass;
@ -87,4 +88,23 @@ public class RequestHandlersTest extends SolrTestCaseJ4 {
assertNull( core.getRequestHandler("/update/asdgadsgas" ) ); // prefix
}
@Test
public void testStatistics() {
SolrCore core = h.getCore();
SolrRequestHandler updateHandler = core.getRequestHandler("/update");
SolrRequestHandler termHandler = core.getRequestHandler("/terms");
assertU(adoc("id", "47",
"text", "line up and fly directly at the enemy death cannons, clogging them with wreckage!"));
assertU(commit());
NamedList updateStats = updateHandler.getStatistics();
NamedList termStats = termHandler.getStatistics();
Double updateTime = (Double) updateStats.get("totalTime");
Double termTime = (Double) termStats.get("totalTime");
assertFalse("RequestHandlers should not share statistics!", updateTime.equals(termTime));
}
}

View File

@ -42,7 +42,8 @@ public class SolrIgnoredThreadsFilter implements ThreadFilter {
return true;
}
if (threadName.startsWith("facetExecutor-") ||
if (threadName.startsWith("facetExecutor-") ||
threadName.startsWith("metrics-") ||
threadName.startsWith("cmdDistribExecutor-") ||
threadName.startsWith("httpShardExecutor-")) {
return true;