From 03ed8213cb1b9fd83c3498918080ec9fe8aec2b0 Mon Sep 17 00:00:00 2001 From: Alan Woodward Date: Mon, 29 Oct 2012 22:13:03 +0000 Subject: [PATCH] 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 --- solr/CHANGES.txt | 4 ++ solr/core/ivy.xml | 1 + .../solr/handler/RequestHandlerBase.java | 64 +++++++++++++------ .../apache/solr/core/RequestHandlersTest.java | 20 ++++++ .../apache/solr/SolrIgnoredThreadsFilter.java | 3 +- 5 files changed, 71 insertions(+), 21 deletions(-) diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index 63c407c263e..1b3fc8f9450 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -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 ---------------------- diff --git a/solr/core/ivy.xml b/solr/core/ivy.xml index c49d15d7622..7fb9af6c05c 100644 --- a/solr/core/ivy.xml +++ b/solr/core/ivy.xml @@ -28,6 +28,7 @@ + diff --git a/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java b/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java index 20d05d0baab..d446e6852c9 100644 --- a/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java +++ b/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java @@ -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 getStatistics() { NamedList lst = new SimpleOrderedMap(); 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; } diff --git a/solr/core/src/test/org/apache/solr/core/RequestHandlersTest.java b/solr/core/src/test/org/apache/solr/core/RequestHandlersTest.java index b9e9bf7fb97..3bb981d9f52 100755 --- a/solr/core/src/test/org/apache/solr/core/RequestHandlersTest.java +++ b/solr/core/src/test/org/apache/solr/core/RequestHandlersTest.java @@ -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)); + } } diff --git a/solr/test-framework/src/java/org/apache/solr/SolrIgnoredThreadsFilter.java b/solr/test-framework/src/java/org/apache/solr/SolrIgnoredThreadsFilter.java index 0a915d29e6b..2afbe6490db 100644 --- a/solr/test-framework/src/java/org/apache/solr/SolrIgnoredThreadsFilter.java +++ b/solr/test-framework/src/java/org/apache/solr/SolrIgnoredThreadsFilter.java @@ -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;