aboutsummaryrefslogtreecommitdiffstats
path: root/container-search
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@yahoo-inc.com>2017-05-18 11:34:08 +0200
committerJon Bratseth <bratseth@yahoo-inc.com>2017-05-18 11:34:08 +0200
commite0af559f58687029780ab6793c3375f0379d16a7 (patch)
treeb8f661a30f6fd587d73f6efaf7077603ce5a5ab5 /container-search
parent97b632d12a35cace208764df3ca7ecc7f7e20755 (diff)
Trace fill request
Diffstat (limited to 'container-search')
-rw-r--r--container-search/src/main/java/com/yahoo/search/Searcher.java7
-rw-r--r--container-search/src/main/java/com/yahoo/search/searchchain/Execution.java28
-rw-r--r--container-search/src/test/java/com/yahoo/search/searchchain/test/SearchChainTestCase.java15
-rw-r--r--container-search/src/test/java/com/yahoo/search/searchchain/test/TraceTestCase.java229
4 files changed, 190 insertions, 89 deletions
diff --git a/container-search/src/main/java/com/yahoo/search/Searcher.java b/container-search/src/main/java/com/yahoo/search/Searcher.java
index 3c4d3332144..69025271430 100644
--- a/container-search/src/main/java/com/yahoo/search/Searcher.java
+++ b/container-search/src/main/java/com/yahoo/search/Searcher.java
@@ -161,6 +161,13 @@ public abstract class Searcher extends Processor {
if ( ! result.isFilled(summaryClass)) {
fill(result, summaryClass, execution);
}
+ else {
+ int fillRejectTraceAt = 3;
+ if (result.getQuery().getTraceLevel() >= fillRejectTraceAt)
+ result.getQuery().trace("Ignoring fill(" + summaryClass + "): " +
+ ( result.hits().getFilled() == null ? "Hits are unfillable" : "Hits already filled" ) +
+ ": result.hits().getFilled()=" + result.hits().getFilled(), fillRejectTraceAt);
+ }
}
/** Returns a logger unique for the instance subclass */
diff --git a/container-search/src/main/java/com/yahoo/search/searchchain/Execution.java b/container-search/src/main/java/com/yahoo/search/searchchain/Execution.java
index b53ade45d07..cde03c9069d 100644
--- a/container-search/src/main/java/com/yahoo/search/searchchain/Execution.java
+++ b/container-search/src/main/java/com/yahoo/search/searchchain/Execution.java
@@ -516,9 +516,7 @@ public class Execution extends com.yahoo.processing.execution.Execution {
final int traceDependencies = 6;
Query query = (Query) request;
if (query.getTraceLevel() >= traceDependencies) {
- query.trace(new StringBuilder().append(processor.getId())
- .append(" ").append(processor.getDependencies().toString())
- .toString(), traceDependencies);
+ query.trace(processor.getId() + " " + processor.getDependencies(), traceDependencies);
}
}
@@ -582,27 +580,15 @@ public class Execution extends com.yahoo.processing.execution.Execution {
}
private void onInvokingFill(Searcher searcher, Result result, String summaryClass) {
- /* TODO
- final int traceDependencies = 6;
- Query query = (Query) request;
- if (query.getTraceLevel() >= traceDependencies) {
- query.trace(new StringBuilder().append(processor.getId())
- .append(" ").append(processor.getDependencies().toString())
- .toString(), traceDependencies);
- }
- */
+ int traceFillAt = 5;
+ if (trace().getTraceLevel() < traceFillAt) return;
+ trace().trace("Invoke fill(" + summaryClass + ") on " + searcher, traceFillAt);
}
private void onReturningFill(Searcher searcher, Result result, String summaryClass) {
- /* TODO
- final int traceDependencies = 6;
- Query query = (Query) request;
- if (query.getTraceLevel() >= traceDependencies) {
- query.trace(new StringBuilder().append(processor.getId())
- .append(" ").append(processor.getDependencies().toString())
- .toString(), traceDependencies);
- }
- */
+ int traceFillAt = 5;
+ if (trace().getTraceLevel() < traceFillAt) return;
+ trace().trace("Return fill(" + summaryClass + ") on " + searcher, traceFillAt);
}
/** Calls ping on the next search in this chain. If there is no next, a Pong is created and returned. */
diff --git a/container-search/src/test/java/com/yahoo/search/searchchain/test/SearchChainTestCase.java b/container-search/src/test/java/com/yahoo/search/searchchain/test/SearchChainTestCase.java
index ad0c4796549..0d87d4448f4 100644
--- a/container-search/src/test/java/com/yahoo/search/searchchain/test/SearchChainTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/searchchain/test/SearchChainTestCase.java
@@ -2,6 +2,7 @@
package com.yahoo.search.searchchain.test;
import static com.yahoo.search.searchchain.test.SimpleSearchChain.searchChain;
+import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Arrays;
@@ -18,6 +19,7 @@ import com.yahoo.search.Result;
import com.yahoo.search.Searcher;
import com.yahoo.search.searchchain.Execution;
import com.yahoo.search.searchchain.SearchChain;
+import org.junit.Test;
/**
* Tests basic search chain functionality - creation, inheritance and ordering
@@ -25,17 +27,15 @@ import com.yahoo.search.searchchain.SearchChain;
* @author bratseth
*/
@SuppressWarnings("deprecation")
-public class SearchChainTestCase extends junit.framework.TestCase {
-
- public SearchChainTestCase(String name) {
- super(name);
- }
+public class SearchChainTestCase {
+ @Test
public void testEmptySearchChain() {
SearchChain empty = new SearchChain(new ComponentId("empty"));
assertEquals("empty", empty.getId().getName());
}
+ @Test
public void testSearchChainCreation() {
assertEquals("test",searchChain.getId().stringValue());
assertEquals("test",searchChain.getId().getName());
@@ -59,22 +59,27 @@ public class SearchChainTestCase extends junit.framework.TestCase {
assertEquals(new HashSet<>(correct),new HashSet<>(test));
}
+ @Test
public void testSearchChainToStringEmpty() {
assertEquals("chain 'test' []", new Chain<>(new ComponentId("test"), createSearchers(0)).toString());
}
+ @Test
public void testSearchChainToStringVeryShort() {
assertEquals("chain 'test' [s1]", new Chain<>(new ComponentId("test"),createSearchers(1)).toString());
}
+ @Test
public void testSearchChainToStringShort() {
assertEquals("chain 'test' [s1 -> s2 -> s3]", new Chain<>(new ComponentId("test"),createSearchers(3)).toString());
}
+ @Test
public void testSearchChainToStringLong() {
assertEquals("chain 'test' [s1 -> s2 -> ... -> s4]", new Chain<>(new ComponentId("test"),createSearchers(4)).toString());
}
+ @Test
public void testSearchChainToStringVeryLong() {
assertEquals("chain 'test' [s1 -> s2 -> ... -> s10]", new Chain<>(new ComponentId("test"),createSearchers(10)).toString());
}
diff --git a/container-search/src/test/java/com/yahoo/search/searchchain/test/TraceTestCase.java b/container-search/src/test/java/com/yahoo/search/searchchain/test/TraceTestCase.java
index a0641374a62..0833fef47bf 100644
--- a/container-search/src/test/java/com/yahoo/search/searchchain/test/TraceTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/searchchain/test/TraceTestCase.java
@@ -1,13 +1,16 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.search.searchchain.test;
+import com.yahoo.component.ComponentId;
import com.yahoo.component.chain.Chain;
import com.yahoo.search.Query;
import com.yahoo.search.Result;
import com.yahoo.search.Searcher;
+import com.yahoo.search.result.Hit;
import com.yahoo.search.searchchain.Execution;
import com.yahoo.yolean.trace.TraceNode;
import com.yahoo.yolean.trace.TraceVisitor;
+import org.junit.Test;
import java.io.IOException;
import java.io.StringWriter;
@@ -16,38 +19,112 @@ import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
/**
* Tests tracing scenarios where traces from multiple executions over the same query are involved.
*
* @author bratseth
*/
-public class TraceTestCase extends junit.framework.TestCase {
+public class TraceTestCase {
+ @Test
public void testTracingOnCorrectAPIUseNonParallel() {
assertTracing(true,false);
}
+ @Test
public void testTracingOnIncorrectAPIUseNonParallel() {
assertTracing(false,false);
}
+ @Test
public void testTracingOnCorrectAPIUseParallel() {
assertTracing(true, true);
}
+ @Test
public void testTracingOnIncorrectAPIUseParallel() {
assertTracing(false,true);
}
+
+ @Test
+ public void testTraceInvocationsUnfillableHits() {
+ final int traceLevel = 5;
+ Query query = new Query("?tracelevel=" + traceLevel);
+ Chain<Searcher> forkingChain = new Chain<>(new Tracer("tracer1"),
+ new Tracer("tracer2"),
+ new Backend("backend1", false));
+ Execution execution = new Execution(forkingChain, Execution.Context.createContextStub());
+ Result result = execution.search(query);
+ execution.fill(result, "mySummary");
+
+ Iterator<String> trace = collectTrace(query).iterator();
+ assertEquals("(level start)", trace.next());
+ assertEquals(" No query profile is used", trace.next());
+ trace.next(); // (properties trace: not checked)
+ assertEquals(" (level start)", trace.next());
+ assertEquals(" Invoke searcher 'tracer1'", trace.next());
+ assertEquals(" During tracer1: 0", trace.next());
+ assertEquals(" Invoke searcher 'tracer2'", trace.next());
+ assertEquals(" During tracer2: 0", trace.next());
+ assertEquals(" Invoke searcher 'backend1'", trace.next());
+ assertEquals(" Return searcher 'backend1'", trace.next());
+ assertEquals(" Return searcher 'tracer2'", trace.next());
+ assertEquals(" Return searcher 'tracer1'", trace.next());
+ assertEquals(" Invoke fill(mySummary) on searcher 'tracer1'", trace.next());
+ assertEquals(" Ignoring fill(mySummary): Hits are unfillable: result.hits().getFilled()=null", trace.next());
+ assertEquals(" Return fill(mySummary) on searcher 'tracer1'", trace.next());
+ assertEquals(" (level end)", trace.next());
+ assertEquals("(level end)", trace.next());
+ assertFalse(trace.hasNext());
+ }
- @SuppressWarnings("deprecation")
- public void assertTracing(boolean carryOverContext,boolean parallel) {
- Query query=new Query("?tracelevel=1");
+ @Test
+ public void testTraceInvocationsFillableHits() {
+ final int traceLevel = 5;
+ Query query = new Query("?tracelevel=" + traceLevel);
+ Chain<Searcher> forkingChain = new Chain<>(new Tracer("tracer1"),
+ new Tracer("tracer2"),
+ new Backend("backend1", true));
+ Execution execution = new Execution(forkingChain, Execution.Context.createContextStub());
+ Result result = execution.search(query);
+ execution.fill(result, "mySummary");
+
+ Iterator<String> trace = collectTrace(query).iterator();
+ assertEquals("(level start)", trace.next());
+ assertEquals(" No query profile is used", trace.next());
+ trace.next(); // (properties trace: not checked)
+ assertEquals(" (level start)", trace.next());
+ assertEquals(" Invoke searcher 'tracer1'", trace.next());
+ assertEquals(" During tracer1: 0", trace.next());
+ assertEquals(" Invoke searcher 'tracer2'", trace.next());
+ assertEquals(" During tracer2: 0", trace.next());
+ assertEquals(" Invoke searcher 'backend1'", trace.next());
+ assertEquals(" Return searcher 'backend1'", trace.next());
+ assertEquals(" Return searcher 'tracer2'", trace.next());
+ assertEquals(" Return searcher 'tracer1'", trace.next());
+ assertEquals(" Invoke fill(mySummary) on searcher 'tracer1'", trace.next());
+ assertEquals(" Invoke fill(mySummary) on searcher 'tracer2'", trace.next());
+ assertEquals(" Invoke fill(mySummary) on searcher 'backend1'", trace.next());
+ assertEquals(" Return fill(mySummary) on searcher 'backend1'", trace.next());
+ assertEquals(" Return fill(mySummary) on searcher 'tracer2'", trace.next());
+ assertEquals(" Return fill(mySummary) on searcher 'tracer1'", trace.next());
+ assertEquals(" (level end)", trace.next());
+ assertEquals("(level end)", trace.next());
+ assertFalse(trace.hasNext());
+ }
+
+ private void assertTracing(boolean carryOverContext, boolean parallel) {
+ Query query = new Query("?tracelevel=1");
query.trace("Before execution",1);
- Chain<Searcher> forkingChain=new Chain<>(new Tracer("forker"),new Forker(carryOverContext,parallel,new Tracer("branch 1"),new Tracer("branch 2")));
+ Chain<Searcher> forkingChain = new Chain<>(new Tracer("forker"),
+ new Forker(carryOverContext, parallel,
+ new Tracer("branch 1") ,
+ new Tracer("branch 2")));
new Execution(forkingChain, Execution.Context.createContextStub()).search(query);
- // printTrace(query);
-
if (carryOverContext)
assertTraceWithChildExecutionMessages(query);
else if (parallel)
@@ -60,20 +137,20 @@ public class TraceTestCase extends junit.framework.TestCase {
// The valid and usual trace
private void assertTraceWithChildExecutionMessages(Query query) {
- Iterator<String> trace=collectTrace(query).iterator();
- assertEquals("(level start)",trace.next());
- assertEquals(" No query profile is used",trace.next());
- assertEquals(" Before execution",trace.next());
- assertEquals(" (level start)",trace.next());
- assertEquals(" During forker: 0",trace.next());
- assertEquals(" (level start)",trace.next());
- assertEquals(" During branch 1: 0",trace.next());
- assertEquals(" (level end)",trace.next());
- assertEquals(" (level start)",trace.next());
+ Iterator<String> trace = collectTrace(query).iterator();
+ assertEquals("(level start)", trace.next());
+ assertEquals(" No query profile is used", trace.next());
+ assertEquals(" Before execution", trace.next());
+ assertEquals(" (level start)", trace.next());
+ assertEquals(" During forker: 0", trace.next());
+ assertEquals(" (level start)", trace.next());
+ assertEquals(" During branch 1: 0", trace.next());
+ assertEquals(" (level end)", trace.next());
+ assertEquals(" (level start)", trace.next());
assertEquals(" During branch 2: 0", trace.next());
- assertEquals(" (level end)",trace.next());
- assertEquals(" (level end)",trace.next());
- assertEquals("(level end)",trace.next());
+ assertEquals(" (level end)", trace.next());
+ assertEquals(" (level end)", trace.next());
+ assertEquals("(level end)", trace.next());
assertFalse(trace.hasNext());
}
@@ -81,19 +158,19 @@ public class TraceTestCase extends junit.framework.TestCase {
// where the message of the execution subtrees is empty rather than "child execution". This is fine.
private void assertTrace(Query query) {
Iterator<String> trace=collectTrace(query).iterator();
- assertEquals("(level start)",trace.next());
- assertEquals(" No query profile is used",trace.next());
- assertEquals(" Before execution",trace.next());
- assertEquals(" (level start)",trace.next());
- assertEquals(" During forker: 0",trace.next());
- assertEquals(" (level start)",trace.next());
- assertEquals(" During branch 1: 0",trace.next());
- assertEquals(" (level end)",trace.next());
- assertEquals(" (level start)",trace.next());
+ assertEquals("(level start)", trace.next());
+ assertEquals(" No query profile is used", trace.next());
+ assertEquals(" Before execution", trace.next());
+ assertEquals(" (level start)", trace.next());
+ assertEquals(" During forker: 0", trace.next());
+ assertEquals(" (level start)", trace.next());
+ assertEquals(" During branch 1: 0", trace.next());
+ assertEquals(" (level end)", trace.next());
+ assertEquals(" (level start)", trace.next());
assertEquals(" During branch 2: 0", trace.next());
- assertEquals(" (level end)",trace.next());
- assertEquals(" (level end)",trace.next());
- assertEquals("(level end)",trace.next());
+ assertEquals(" (level end)", trace.next());
+ assertEquals(" (level end)", trace.next());
+ assertEquals("(level end)", trace.next());
assertFalse(trace.hasNext());
}
@@ -101,27 +178,27 @@ public class TraceTestCase extends junit.framework.TestCase {
// but all the trace messages are present.
private void assertIncorrectlyNestedTrace(Query query) {
Iterator<String> trace=collectTrace(query).iterator();
- assertEquals("(level start)",trace.next());
- assertEquals(" No query profile is used",trace.next());
- assertEquals(" Before execution",trace.next());
- assertEquals(" (level start)",trace.next());
- assertEquals(" During forker: 0",trace.next());
- assertEquals(" (level start)",trace.next());
- assertEquals(" During branch 1: 0",trace.next());
- assertEquals(" (level start)",trace.next());
+ assertEquals("(level start)", trace.next());
+ assertEquals(" No query profile is used", trace.next());
+ assertEquals(" Before execution", trace.next());
+ assertEquals(" (level start)", trace.next());
+ assertEquals(" During forker: 0", trace.next());
+ assertEquals(" (level start)", trace.next());
+ assertEquals(" During branch 1: 0", trace.next());
+ assertEquals(" (level start)", trace.next());
assertEquals(" During branch 2: 0", trace.next());
- assertEquals(" (level end)",trace.next());
- assertEquals(" (level end)",trace.next());
- assertEquals(" (level end)",trace.next());
- assertEquals("(level end)",trace.next());
+ assertEquals(" (level end)", trace.next());
+ assertEquals(" (level end)", trace.next());
+ assertEquals(" (level end)", trace.next());
+ assertEquals("(level end)", trace.next());
assertFalse(trace.hasNext());
}
private void assertCorrectRendering(Query query) {
try {
- StringWriter writer=new StringWriter();
+ StringWriter writer = new StringWriter();
query.getContext(false).render(writer);
- String expected=
+ String expected =
"<meta type=\"context\">\n" +
"\n" +
" <p>No query profile is used</p>\n" +
@@ -130,7 +207,7 @@ public class TraceTestCase extends junit.framework.TestCase {
"\n" +
" <p>\n" +
" <p>During forker: 0";
- assertEquals(expected,writer.toString().substring(0,expected.length()));
+ assertEquals(expected, writer.toString().substring(0, expected.length()));
}
catch (IOException e) {
throw new RuntimeException(e);
@@ -138,15 +215,15 @@ public class TraceTestCase extends junit.framework.TestCase {
}
private List<String> collectTrace(Query query) {
- TraceCollector collector=new TraceCollector();
+ TraceCollector collector = new TraceCollector();
query.getContext(false).getTrace().accept(collector);
return collector.trace();
}
private static class TraceCollector extends TraceVisitor {
- private List<String> trace=new ArrayList<>();
- private StringBuilder indent=new StringBuilder();
+ private List<String> trace = new ArrayList<>();
+ private StringBuilder indent = new StringBuilder();
@Override
public void entering(TraceNode node) {
@@ -156,14 +233,14 @@ public class TraceTestCase extends junit.framework.TestCase {
@Override
public void leaving(TraceNode end) {
- indent.setLength(indent.length()-2);
+ indent.setLength(indent.length() - 2);
trace.add(indent + "(level end)");
}
@Override
public void visit(TraceNode node) {
if (node.isRoot()) return;
- if (node.payload()==null) return;
+ if (node.payload() == null) return;
trace.add(indent + node.payload().toString());
}
@@ -173,15 +250,16 @@ public class TraceTestCase extends junit.framework.TestCase {
private static class Tracer extends Searcher {
private String name;
- private int counter=0;
+ private int counter = 0;
public Tracer(String name) {
- this.name=name;
+ super(new ComponentId(name));
+ this.name = name;
}
@Override
public Result search(Query query, Execution execution) {
- query.trace("During " + name + ": " + (counter++) ,1);
+ query.trace("During " + name + ": " + (counter++),1);
return execution.search(query);
}
}
@@ -196,20 +274,21 @@ public class TraceTestCase extends junit.framework.TestCase {
/** If true, simulate parallel execution by cloning the query */
private boolean parallel;
- public Forker(boolean carryOverContext,boolean parallel,Searcher ... branches) {
- this.carryOverContext=carryOverContext;
- this.parallel=parallel;
- this.branches=Arrays.asList(branches);
+ public Forker(boolean carryOverContext, boolean parallel, Searcher ... branches) {
+ this.carryOverContext = carryOverContext;
+ this.parallel = parallel;
+ this.branches = Arrays.asList(branches);
}
@SuppressWarnings("deprecation")
@Override
public Result search(Query query, Execution execution) {
- Result result=execution.search(query);
+ Result result = execution.search(query);
for (Searcher branch : branches) {
- Query branchQuery=parallel ? query.clone() : query;
- Result branchResult=
- ( carryOverContext ? new Execution(branch,execution.context()) : new Execution(branch, Execution.Context.createContextStub())).search(branchQuery);
+ Query branchQuery = parallel ? query.clone() : query;
+ Result branchResult =
+ ( carryOverContext ? new Execution(branch, execution.context()) :
+ new Execution(branch, Execution.Context.createContextStub())).search(branchQuery);
result.hits().add(branchResult.hits());
result.mergeWith(branchResult);
}
@@ -218,4 +297,28 @@ public class TraceTestCase extends junit.framework.TestCase {
}
+ private static class Backend extends Searcher {
+
+ private final boolean fillableHits;
+
+ public Backend(String name, boolean fillableHits) {
+ super(new ComponentId(name));
+ this.fillableHits = fillableHits;
+ }
+
+ @Override
+ public Result search(Query query, Execution execution) {
+ Result result = execution.search(query);
+ Hit hit0 = new Hit("hit:0");
+ Hit hit1 = new Hit("hit:1");
+ if (fillableHits) {
+ hit0.setFillable();
+ hit1.setFillable();
+ }
+ result.hits().add(hit0);
+ result.hits().add(hit1);
+ return result;
+ }
+ }
+
}