diff options
-rw-r--r-- | config-model/src/main/java/com/yahoo/vespa/model/admin/monitoring/VespaMetricSet.java | 3 | ||||
-rw-r--r-- | container-core/src/main/java/com/yahoo/container/core/config/testutil/HandlersConfigurerTestWrapper.java | 3 | ||||
-rw-r--r-- | container-search/src/main/java/com/yahoo/search/handler/HttpSearchResponse.java | 47 | ||||
-rw-r--r-- | container-search/src/main/java/com/yahoo/search/handler/SearchHandler.java | 15 | ||||
-rw-r--r-- | container-search/src/test/java/com/yahoo/search/handler/SearchHandlerTest.java (renamed from container-search/src/test/java/com/yahoo/search/handler/test/SearchHandlerTestCase.java) | 12 | ||||
-rw-r--r-- | container-search/src/test/java/com/yahoo/search/handler/test/config/chains.cfg | 16 | ||||
-rw-r--r-- | container-search/src/test/java/com/yahoo/search/handler/test/config/handlers.cfg | 12 | ||||
-rw-r--r-- | container-search/src/test/java/com/yahoo/search/handler/test/config/handlers2/chains.cfg | 8 | ||||
-rw-r--r-- | container-search/src/test/java/com/yahoo/search/handler/test/config/handlersInvalid/handlers.cfg | 2 |
9 files changed, 76 insertions, 42 deletions
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/admin/monitoring/VespaMetricSet.java b/config-model/src/main/java/com/yahoo/vespa/model/admin/monitoring/VespaMetricSet.java index 1743d5f4432..65b70bdce33 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/admin/monitoring/VespaMetricSet.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/admin/monitoring/VespaMetricSet.java @@ -322,6 +322,7 @@ public class VespaMetricSet { metrics.add(new Metric("documents_total.count")); metrics.add(new Metric("dispatch_internal.rate")); metrics.add(new Metric("dispatch_fdispatch.rate")); + addMetric(metrics, "jdisc.search.render_latency", Set.of("min", "max", "count", "sum", "last")); metrics.add(new Metric("totalhits_per_query.max")); metrics.add(new Metric("totalhits_per_query.sum")); @@ -783,7 +784,7 @@ public class VespaMetricSet { return metrics; } - private static void addMetric(Set<Metric> metrics, String metricName, List<String> aggregateSuffices) { + private static void addMetric(Set<Metric> metrics, String metricName, Iterable<String> aggregateSuffices) { for (String suffix : aggregateSuffices) { metrics.add(new Metric(metricName + "." + suffix)); } diff --git a/container-core/src/main/java/com/yahoo/container/core/config/testutil/HandlersConfigurerTestWrapper.java b/container-core/src/main/java/com/yahoo/container/core/config/testutil/HandlersConfigurerTestWrapper.java index d98a865e1fb..087be0f17c5 100644 --- a/container-core/src/main/java/com/yahoo/container/core/config/testutil/HandlersConfigurerTestWrapper.java +++ b/container-core/src/main/java/com/yahoo/container/core/config/testutil/HandlersConfigurerTestWrapper.java @@ -13,7 +13,9 @@ import com.yahoo.container.core.config.HandlersConfigurerDi; import com.yahoo.container.di.CloudSubscriberFactory; import com.yahoo.container.di.ComponentDeconstructor; import com.yahoo.container.handler.threadpool.ContainerThreadPool; +import com.yahoo.jdisc.Metric; import com.yahoo.jdisc.handler.RequestHandler; +import com.yahoo.jdisc.test.MockMetric; import com.yahoo.language.Linguistics; import com.yahoo.language.simple.SimpleLinguistics; @@ -139,6 +141,7 @@ public class HandlersConfigurerTestWrapper { // Needed by e.g. SearchHandler bind(Linguistics.class).to(SimpleLinguistics.class).in(Scopes.SINGLETON); bind(ContainerThreadPool.class).to(SimpleContainerThreadpool.class); + bind(Metric.class).to(MockMetric.class); } }); } diff --git a/container-search/src/main/java/com/yahoo/search/handler/HttpSearchResponse.java b/container-search/src/main/java/com/yahoo/search/handler/HttpSearchResponse.java index d636d3bc925..7ef9ebad010 100644 --- a/container-search/src/main/java/com/yahoo/search/handler/HttpSearchResponse.java +++ b/container-search/src/main/java/com/yahoo/search/handler/HttpSearchResponse.java @@ -1,20 +1,15 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.search.handler; -import java.io.IOException; -import java.io.OutputStream; -import java.util.Collections; -import java.util.List; -import java.util.Map; - import com.google.common.util.concurrent.ListenableFuture; import com.yahoo.collections.ListMap; -import com.yahoo.container.jdisc.ExtendedResponse; import com.yahoo.container.handler.Coverage; import com.yahoo.container.handler.Timing; +import com.yahoo.container.jdisc.ExtendedResponse; import com.yahoo.container.logging.AccessLogEntry; import com.yahoo.container.logging.HitCounts; import com.yahoo.jdisc.HeaderFields; +import com.yahoo.jdisc.Metric; import com.yahoo.jdisc.handler.CompletionHandler; import com.yahoo.jdisc.handler.ContentChannel; import com.yahoo.processing.execution.Execution.Trace.LogValue; @@ -25,6 +20,13 @@ import com.yahoo.search.Result; import com.yahoo.search.query.context.QueryContext; import com.yahoo.yolean.trace.TraceNode; +import java.io.IOException; +import java.io.OutputStream; +import java.time.Duration; +import java.util.Collections; +import java.util.List; +import java.util.Map; + /** * Wrap the result of a query as an HTTP response. * @@ -35,20 +37,21 @@ public class HttpSearchResponse extends ExtendedResponse { private final Result result; private final Query query; private final Renderer<Result> rendererCopy; + private final Metric metric; private final Timing timing; private final HitCounts hitCounts; private final TraceNode trace; - public HttpSearchResponse(int status, Result result, Query query, Renderer renderer) { - this(status, result, query, renderer, null); + public HttpSearchResponse(int status, Result result, Query query, Renderer<Result> renderer) { + this(status, result, query, renderer, null, null); } - HttpSearchResponse(int status, Result result, Query query, Renderer renderer, TraceNode trace) { + HttpSearchResponse(int status, Result result, Query query, Renderer<Result> renderer, TraceNode trace, Metric metric) { super(status); this.query = query; this.result = result; this.rendererCopy = renderer; - + this.metric = metric; this.timing = SearchResponse.createTiming(query, result); this.hitCounts = SearchResponse.createHitCounts(query, result); this.trace = trace; @@ -98,7 +101,11 @@ public class HttpSearchResponse extends ExtendedResponse { } try { try { - waitableRender(output); + long nanoStart = System.nanoTime(); + ListenableFuture<Boolean> promise = waitableRender(output); + if (metric != null) { + promise.addListener(new RendererLatencyReporter(nanoStart), Runnable::run); + } } finally { if (!(rendererCopy instanceof AsynchronousSectionedRenderer)) { output.flush(); @@ -178,4 +185,20 @@ public class HttpSearchResponse extends ExtendedResponse { : context::logValueIterator; } + private class RendererLatencyReporter implements Runnable { + + final long nanoStart; + + RendererLatencyReporter(long nanoStart) { this.nanoStart = nanoStart; } + + @Override + public void run() { + long latencyMillis = Duration.ofNanos(System.nanoTime() - nanoStart).toMillis(); + Metric.Context ctx = metric.createContext(Map.of( + SearchHandler.RENDERER_DIMENSION, rendererCopy.getClassName(), + SearchHandler.MIME_DIMENSION, rendererCopy.getMimeType())); + metric.set(SearchHandler.RENDER_LATENCY_METRIC, latencyMillis, ctx); + } + } + } diff --git a/container-search/src/main/java/com/yahoo/search/handler/SearchHandler.java b/container-search/src/main/java/com/yahoo/search/handler/SearchHandler.java index e2c15b6e35b..f81aab4259d 100644 --- a/container-search/src/main/java/com/yahoo/search/handler/SearchHandler.java +++ b/container-search/src/main/java/com/yahoo/search/handler/SearchHandler.java @@ -11,6 +11,7 @@ import com.yahoo.container.QrSearchersConfig; import com.yahoo.container.core.ChainsConfig; import com.yahoo.container.core.ContainerHttpConfig; import com.yahoo.container.handler.threadpool.ContainerThreadPool; +import com.yahoo.container.jdisc.AclMapping; import com.yahoo.container.jdisc.HttpMethodAclMapping; import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.container.jdisc.HttpResponse; @@ -21,8 +22,6 @@ import com.yahoo.container.logging.AccessLog; import com.yahoo.io.IOUtils; import com.yahoo.jdisc.Metric; import com.yahoo.jdisc.Request; -import com.yahoo.container.jdisc.AclMapping; -import com.yahoo.container.jdisc.RequestView; import com.yahoo.language.Linguistics; import com.yahoo.net.HostName; import com.yahoo.net.UriTools; @@ -88,6 +87,9 @@ public class SearchHandler extends LoggingRequestHandler { /** Event name for number of connections to the search subsystem */ private static final String SEARCH_CONNECTIONS = "search_connections"; + static final String RENDER_LATENCY_METRIC = "jdisc.search.render_latency"; + static final String MIME_DIMENSION = "mime"; + static final String RENDERER_DIMENSION = "renderer"; private static final String JSON_CONTENT_TYPE = "application/json"; @@ -230,6 +232,8 @@ public class SearchHandler extends LoggingRequestHandler { new ExecutionFactory(chainsConfig, indexInfo, clusters, searchers, specialtokens, linguistics, renderers)); } + Metric metric() { return metric; } + private static int examineExecutor(Executor executor) { if (executor instanceof ThreadPoolExecutor) { return ((ThreadPoolExecutor) executor).getMaximumPoolSize(); @@ -273,7 +277,7 @@ public class SearchHandler extends LoggingRequestHandler { private HttpResponse errorResponse(HttpRequest request, ErrorMessage errorMessage) { Query query = new Query(); Result result = new Result(query, errorMessage); - Renderer renderer = getRendererCopy(ComponentSpecification.fromString(request.getProperty("format"))); + Renderer<Result> renderer = getRendererCopy(ComponentSpecification.fromString(request.getProperty("format"))); return new HttpSearchResponse(getHttpResponseStatus(request, result), result, query, renderer); } @@ -328,10 +332,11 @@ public class SearchHandler extends LoggingRequestHandler { } // Transform result to response - Renderer renderer = toRendererCopy(query.getPresentation().getRenderer()); + Renderer<Result> renderer = toRendererCopy(query.getPresentation().getRenderer()); HttpSearchResponse response = new HttpSearchResponse(getHttpResponseStatus(request, result), result, query, renderer, - extractTraceNode(query)); + extractTraceNode(query), + metric); response.setRequestType(Request.RequestType.READ); hostResponseHeaderKey.ifPresent(key -> response.headers().add(key, selfHostname)); diff --git a/container-search/src/test/java/com/yahoo/search/handler/test/SearchHandlerTestCase.java b/container-search/src/test/java/com/yahoo/search/handler/SearchHandlerTest.java index 2eb5901b786..2b584c7b285 100644 --- a/container-search/src/test/java/com/yahoo/search/handler/test/SearchHandlerTestCase.java +++ b/container-search/src/test/java/com/yahoo/search/handler/SearchHandlerTest.java @@ -1,5 +1,5 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.search.handler.test; +package com.yahoo.search.handler; import com.yahoo.container.Container; import com.yahoo.container.core.config.testutil.HandlersConfigurerTestWrapper; @@ -10,12 +10,11 @@ import com.yahoo.container.jdisc.ThreadedHttpRequestHandler; import com.yahoo.io.IOUtils; import com.yahoo.jdisc.Request; import com.yahoo.jdisc.handler.RequestHandler; +import com.yahoo.jdisc.test.MockMetric; import com.yahoo.net.HostName; import com.yahoo.search.Query; import com.yahoo.search.Result; import com.yahoo.search.Searcher; -import com.yahoo.search.handler.HttpSearchResponse; -import com.yahoo.search.handler.SearchHandler; import com.yahoo.search.rendering.XmlRenderer; import com.yahoo.search.result.ErrorMessage; import com.yahoo.search.result.Hit; @@ -45,7 +44,7 @@ import static org.junit.Assert.assertTrue; /** * @author bratseth */ -public class SearchHandlerTestCase { +public class SearchHandlerTest { private static final String testDir = "src/test/java/com/yahoo/search/handler/test/config"; private static final String myHostnameHeader = "my-hostname-header"; @@ -59,6 +58,7 @@ public class SearchHandlerTestCase { private RequestHandlerTestDriver driver = null; private HandlersConfigurerTestWrapper configurer = null; + private MockMetric metric; private SearchHandler searchHandler; @Before @@ -72,6 +72,7 @@ public class SearchHandlerTestCase { configurer = new HandlersConfigurerTestWrapper(new Container(), configId); searchHandler = (SearchHandler)configurer.getRequestHandlerRegistry().getComponent(SearchHandler.class.getName()); + metric = (MockMetric) searchHandler.metric(); driver = new RequestHandlerTestDriver(searchHandler); } @@ -289,6 +290,7 @@ public class SearchHandlerTestCase { assertEquals(expected, response.readAll()); assertEquals(200, response.getStatus()); assertEquals(selfHostname, response.getResponse().headers().get(myHostnameHeader).get(0)); + assertTrue(metric.metrics().containsKey(SearchHandler.RENDER_LATENCY_METRIC)); } @Test @@ -310,7 +312,7 @@ public class SearchHandlerTestCase { } private void assertHandlerResponse(int status, String responseData, String handlerName) throws Exception { - RequestHandler forwardingHandler = configurer.getRequestHandlerRegistry().getComponent("com.yahoo.search.handler.test.SearchHandlerTestCase$" + handlerName + "Handler"); + RequestHandler forwardingHandler = configurer.getRequestHandlerRegistry().getComponent("com.yahoo.search.handler.SearchHandlerTest$" + handlerName + "Handler"); try (RequestHandlerTestDriver forwardingDriver = new RequestHandlerTestDriver(forwardingHandler)) { RequestHandlerTestDriver.MockResponseHandler response = forwardingDriver.sendRequest("http://localhost/" + handlerName + "?query=test"); response.awaitResponse(); diff --git a/container-search/src/test/java/com/yahoo/search/handler/test/config/chains.cfg b/container-search/src/test/java/com/yahoo/search/handler/test/config/chains.cfg index 9a16c6ed1e7..f7eba221ef1 100644 --- a/container-search/src/test/java/com/yahoo/search/handler/test/config/chains.cfg +++ b/container-search/src/test/java/com/yahoo/search/handler/test/config/chains.cfg @@ -1,20 +1,20 @@ chains[4] chains[0].id default chains[0].components[1] -chains[0].components[0] com.yahoo.search.handler.test.SearchHandlerTestCase$TestSearcher +chains[0].components[0] com.yahoo.search.handler.SearchHandlerTest$TestSearcher chains[1].id classLoadingError chains[1].components[1] -chains[1].components[0] com.yahoo.search.handler.test.SearchHandlerTestCase$ClassLoadingErrorSearcher +chains[1].components[0] com.yahoo.search.handler.SearchHandlerTest$ClassLoadingErrorSearcher chains[2].id exceptionInPlugin chains[2].components[1] -chains[2].components[0] com.yahoo.search.handler.test.SearchHandlerTestCase$ExceptionInPluginSearcher +chains[2].components[0] com.yahoo.search.handler.SearchHandlerTest$ExceptionInPluginSearcher chains[3].id echoingQuery chains[3].components[2] chains[3].components[0] com.yahoo.search.yql.MinimalQueryInserter -chains[3].components[1] com.yahoo.search.handler.test.SearchHandlerTestCase$EchoingQuerySearcher +chains[3].components[1] com.yahoo.search.handler.SearchHandlerTest$EchoingQuerySearcher components[5] -components[0].id com.yahoo.search.handler.test.SearchHandlerTestCase$TestSearcher -components[1].id com.yahoo.search.handler.test.SearchHandlerTestCase$ClassLoadingErrorSearcher -components[2].id com.yahoo.search.handler.test.SearchHandlerTestCase$ExceptionInPluginSearcher -components[3].id com.yahoo.search.handler.test.SearchHandlerTestCase$EchoingQuerySearcher +components[0].id com.yahoo.search.handler.SearchHandlerTest$TestSearcher +components[1].id com.yahoo.search.handler.SearchHandlerTest$ClassLoadingErrorSearcher +components[2].id com.yahoo.search.handler.SearchHandlerTest$ExceptionInPluginSearcher +components[3].id com.yahoo.search.handler.SearchHandlerTest$EchoingQuerySearcher components[4].id com.yahoo.search.yql.MinimalQueryInserter diff --git a/container-search/src/test/java/com/yahoo/search/handler/test/config/handlers.cfg b/container-search/src/test/java/com/yahoo/search/handler/test/config/handlers.cfg index 915da8dc037..12f218581d5 100644 --- a/container-search/src/test/java/com/yahoo/search/handler/test/config/handlers.cfg +++ b/container-search/src/test/java/com/yahoo/search/handler/test/config/handlers.cfg @@ -1,9 +1,9 @@ handler[8] handler[0].id com.yahoo.search.handler.SearchHandler -handler[1].id com.yahoo.search.handler.test.SearchHandlerTestCase$NullReturningHandler -handler[2].id com.yahoo.search.handler.test.SearchHandlerTestCase$NullReturningAsyncHandler -handler[3].id com.yahoo.search.handler.test.SearchHandlerTestCase$ThrowingHandler -handler[4].id com.yahoo.search.handler.test.SearchHandlerTestCase$ThrowingAsyncHandler -handler[5].id com.yahoo.search.handler.test.SearchHandlerTestCase$ForwardingHandler -handler[6].id com.yahoo.search.handler.test.SearchHandlerTestCase$ForwardingAsyncHandler +handler[1].id com.yahoo.search.handler.SearchHandlerTest$NullReturningHandler +handler[2].id com.yahoo.search.handler.SearchHandlerTest$NullReturningAsyncHandler +handler[3].id com.yahoo.search.handler.SearchHandlerTest$ThrowingHandler +handler[4].id com.yahoo.search.handler.SearchHandlerTest$ThrowingAsyncHandler +handler[5].id com.yahoo.search.handler.SearchHandlerTest$ForwardingHandler +handler[6].id com.yahoo.search.handler.SearchHandlerTest$ForwardingAsyncHandler handler[7].id com.yahoo.search.query.profile.compiled.CompiledQueryProfileRegistry diff --git a/container-search/src/test/java/com/yahoo/search/handler/test/config/handlers2/chains.cfg b/container-search/src/test/java/com/yahoo/search/handler/test/config/handlers2/chains.cfg index 2437efdec4f..83db7ef1cc9 100644 --- a/container-search/src/test/java/com/yahoo/search/handler/test/config/handlers2/chains.cfg +++ b/container-search/src/test/java/com/yahoo/search/handler/test/config/handlers2/chains.cfg @@ -1,10 +1,10 @@ chains[2] chains[0].id default chains[0].components[1] -chains[0].components[0] com.yahoo.search.handler.test.SearchHandlerTestCase$TestSearcher +chains[0].components[0] com.yahoo.search.handler.SearchHandlerTest$TestSearcher chains[1].id hello chains[1].components[1] -chains[1].components[0] com.yahoo.search.handler.test.SearchHandlerTestCase$HelloWorldSearcher +chains[1].components[0] com.yahoo.search.handler.SearchHandlerTest$HelloWorldSearcher components[2] -components[0].id com.yahoo.search.handler.test.SearchHandlerTestCase$TestSearcher -components[1].id com.yahoo.search.handler.test.SearchHandlerTestCase$HelloWorldSearcher +components[0].id com.yahoo.search.handler.SearchHandlerTest$TestSearcher +components[1].id com.yahoo.search.handler.SearchHandlerTest$HelloWorldSearcher diff --git a/container-search/src/test/java/com/yahoo/search/handler/test/config/handlersInvalid/handlers.cfg b/container-search/src/test/java/com/yahoo/search/handler/test/config/handlersInvalid/handlers.cfg index 691b37b4955..9dd1aff9d06 100644 --- a/container-search/src/test/java/com/yahoo/search/handler/test/config/handlersInvalid/handlers.cfg +++ b/container-search/src/test/java/com/yahoo/search/handler/test/config/handlersInvalid/handlers.cfg @@ -1,3 +1,3 @@ handler[2] handler[0].id com.yahoo.search.handler.SearchHandler -handler[1].id com.yahoo.search.handler.test.SearchHandlerTestCase$ErrorOnInitializationHandler +handler[1].id com.yahoo.search.handler.SearchHandlerTest$ErrorOnInitializationHandler |