diff --git a/demo/cars/conf/log4j2.xml b/demo/cars/conf/log4j2.xml
index cc9ffe7..c1dcd4c 100644
--- a/demo/cars/conf/log4j2.xml
+++ b/demo/cars/conf/log4j2.xml
@@ -34,6 +34,16 @@
+
+
+ %d [%t] %-5p %M(%F:%L) - %m%n
+
+
+
+
+
+
@@ -44,5 +54,9 @@
+
+
+
+
diff --git a/linden-core/src/main/java/com/xiaomi/linden/core/LindenConfig.java b/linden-core/src/main/java/com/xiaomi/linden/core/LindenConfig.java
index 1df1ade..30a75b6 100644
--- a/linden-core/src/main/java/com/xiaomi/linden/core/LindenConfig.java
+++ b/linden-core/src/main/java/com/xiaomi/linden/core/LindenConfig.java
@@ -93,6 +93,7 @@ public enum CommandType {
private boolean enableSourceFieldCache;
private int indexSearcherParallelThreadNum;
private String lindenWarmerFactory;
+ private int slowQueryThresholdMillis;
private Map fieldSchemaMap = new HashMap<>();
@@ -115,6 +116,7 @@ public LindenConfig() {
this.indexManagerThreadNum = 11;
this.enableSourceFieldCache = false;
this.indexSearcherParallelThreadNum = 2 * Runtime.getRuntime().availableProcessors();
+ this.slowQueryThresholdMillis = 300;
}
public void putToProperties(String key, String val) {
@@ -433,6 +435,14 @@ public LindenConfig setLindenWarmerFactory(String lindenWarmerFactory) {
return this;
}
+ public int getSlowQueryThresholdMillis() {
+ return slowQueryThresholdMillis;
+ }
+
+ public void setSlowQueryThresholdMillis(int slowQueryThresholdMillis) {
+ this.slowQueryThresholdMillis = slowQueryThresholdMillis;
+ }
+
public LindenFieldSchema getFieldSchema(String field) {
LindenFieldSchema fieldSchema = fieldSchemaMap.get(field);
if (fieldSchema != null) {
diff --git a/linden-core/src/main/java/com/xiaomi/linden/core/LindenConfigBuilder.java b/linden-core/src/main/java/com/xiaomi/linden/core/LindenConfigBuilder.java
index 3df1af7..bc94749 100644
--- a/linden-core/src/main/java/com/xiaomi/linden/core/LindenConfigBuilder.java
+++ b/linden-core/src/main/java/com/xiaomi/linden/core/LindenConfigBuilder.java
@@ -58,6 +58,7 @@ public class LindenConfigBuilder {
public static final String SEARCH_THREAD_POOL_JSON_CONFIG = "search.thread.pool.json.config";
public static final String ENABLE_SOURCE_FIELD_CACHE = "enable.source.field.cache";
public static final String INDEX_SEARCHER_PARALLEL_THREAD_NUM = "index.searcher.parallel.thread.num";
+ public static final String SLOW_QUERY_THRESHOLD_MILLIS = "slow.query.threshold.millis";
protected static class FieldInfo {
@@ -119,6 +120,7 @@ public Class> getType() {
fieldMap.put(SEARCH_THREAD_POOL_JSON_CONFIG, new FieldInfo("SearchThreadPoolConfig", String.class));
fieldMap.put(ENABLE_SOURCE_FIELD_CACHE, new FieldInfo("EnableSourceFieldCache", boolean.class));
fieldMap.put(INDEX_SEARCHER_PARALLEL_THREAD_NUM, new FieldInfo("IndexSearcherParallelThreadNum", int.class));
+ fieldMap.put(SLOW_QUERY_THRESHOLD_MILLIS,new FieldInfo("SlowQueryThresholdMillis",int.class));
}
diff --git a/linden-core/src/main/java/com/xiaomi/linden/lucene/query/flexiblequery/FlexibleScoreModelStrategy.java b/linden-core/src/main/java/com/xiaomi/linden/lucene/query/flexiblequery/FlexibleScoreModelStrategy.java
index 8d7cced..e7c1c66 100644
--- a/linden-core/src/main/java/com/xiaomi/linden/lucene/query/flexiblequery/FlexibleScoreModelStrategy.java
+++ b/linden-core/src/main/java/com/xiaomi/linden/lucene/query/flexiblequery/FlexibleScoreModelStrategy.java
@@ -16,7 +16,6 @@
import java.io.IOException;
import java.util.Arrays;
-import java.util.List;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.Query;
@@ -104,7 +103,7 @@ public int position(int field, int term) {
return termMatchedInfo(field, term).position(doc());
}
- public List positions(int field, int term) {
+ public int[] positions(int field, int term) {
return termMatchedInfo(field, term).positions(doc());
}
diff --git a/linden-core/src/main/java/com/xiaomi/linden/lucene/query/flexiblequery/TermDocsEnum.java b/linden-core/src/main/java/com/xiaomi/linden/lucene/query/flexiblequery/TermDocsEnum.java
index c3bb899..0ab3411 100644
--- a/linden-core/src/main/java/com/xiaomi/linden/lucene/query/flexiblequery/TermDocsEnum.java
+++ b/linden-core/src/main/java/com/xiaomi/linden/lucene/query/flexiblequery/TermDocsEnum.java
@@ -14,6 +14,8 @@
package com.xiaomi.linden.lucene.query.flexiblequery;
+import java.io.IOException;
+
import org.apache.lucene.index.DocsAndPositionsEnum;
import org.apache.lucene.search.ComplexExplanation;
import org.apache.lucene.search.DocIdSetIterator;
@@ -21,10 +23,6 @@
import org.apache.lucene.search.Query;
import org.apache.lucene.search.similarities.Similarity;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
public class TermDocsEnum {
protected DocsAndPositionsEnum postings;
@@ -33,16 +31,18 @@ public class TermDocsEnum {
protected int doc;
private int position;
- private List positions;
+ private int[] positions;
private int freq;
protected int termPos = -1;
protected int docFreq = -1;
private int matchedDoc = -1;
private int matchedPosition = -1;
- private List matchedPositions;
+ private int[] matchedPositions;
private int matchedFreq = -1;
private int field;
+ private int initPositionSize = 5;
+
public TermDocsEnum(FlexibleQuery.FlexibleTerm term, int docFreq, DocsAndPositionsEnum postings,
Similarity.SimScorer docScorer, int field, int termPos) throws IOException {
@@ -53,12 +53,15 @@ public TermDocsEnum(FlexibleQuery.FlexibleTerm term, int docFreq, DocsAndPositio
this.docScorer = docScorer;
this.field = field;
this.termPos = termPos;
+ this.positions = new int[initPositionSize];
+ this.matchedPositions = new int[initPositionSize];
}
public FlexibleQuery.FlexibleTerm term() {
return term;
}
+
public float score(int doc) throws IOException {
if (isMatched(doc)) {
return docScorer.score(matchedDoc, matchedFreq);
@@ -77,11 +80,16 @@ public boolean next() throws IOException {
return false;
}
freq = postings.freq();
- positions = new ArrayList<>(freq);
+ if (freq > initPositionSize) {
+ int newSize = 2 * freq;
+ positions = new int[newSize];
+ matchedPositions = new int[newSize];
+ initPositionSize = newSize;
+ }
for (int i = 0; i < freq; i++) {
- positions.add(postings.nextPosition());
+ positions[i] = postings.nextPosition();
}
- position = positions.get(0);
+ position = positions[0];
return true;
}
@@ -98,8 +106,13 @@ public int position(int doc) {
return doc == matchedDoc ? matchedPosition : -1;
}
- public List positions(int doc) {
- return doc == matchedDoc ? matchedPositions : null;
+ public int[] positions(int doc) {
+ if (doc == matchedDoc) {
+ int[] matchedPositionsData = new int[matchedFreq];
+ System.arraycopy(matchedPositions, 0, matchedPositionsData, 0, matchedFreq);
+ return matchedPositionsData;
+ }
+ return new int[0];
}
public String toString() {
@@ -134,10 +147,13 @@ public void saveMatchedInfo() {
this.matchedDoc = doc;
this.matchedPosition = position;
this.matchedFreq = freq;
- this.matchedPositions = positions;
+ for (int i = 0; i < matchedFreq; i++) {
+ matchedPositions[i] = positions[i];
+ }
}
public int getField() {
return field;
}
+
}
diff --git a/linden-core/src/main/java/com/xiaomi/linden/service/CoreLindenServiceImpl.java b/linden-core/src/main/java/com/xiaomi/linden/service/CoreLindenServiceImpl.java
index a102f8d..8c1af3c 100644
--- a/linden-core/src/main/java/com/xiaomi/linden/service/CoreLindenServiceImpl.java
+++ b/linden-core/src/main/java/com/xiaomi/linden/service/CoreLindenServiceImpl.java
@@ -62,6 +62,8 @@
public class CoreLindenServiceImpl implements LindenService.ServiceIface {
private static final Logger LOGGER = LoggerFactory.getLogger(CoreLindenServiceImpl.class);
+ private static final Logger SLOW_LOGGER = LoggerFactory.getLogger("CoreLindenServiceImpl.SlowRequest");
+
private final LindenCluster lindenCluster;
private final BQLCompiler bqlCompiler;
@@ -79,6 +81,7 @@ public class CoreLindenServiceImpl implements LindenService.ServiceIface {
private LindenWarmer lindenWarmer;
private int instanceFuturePoolWaitTimeout;
private int clusterFuturePoolWaitTimeout;
+ private int slowQueryThresholdMillis;
public CoreLindenServiceImpl(final LindenConfig config) throws Exception {
Preconditions.checkArgument(config != null, "LindenConfig can not be null.");
@@ -143,6 +146,8 @@ public CoreLindenServiceImpl(final LindenConfig config) throws Exception {
bqlCompiler = new BQLCompiler(config.getSchema());
+ this.slowQueryThresholdMillis = config.getSlowQueryThresholdMillis();
+
try {
lindenCluster = new CoreLindenCluster(config, shardingStrategy, this);
} catch (Exception e) {
@@ -222,8 +227,9 @@ public Future search(final LindenSearchRequest request) {
public LindenResult apply() {
LindenResult result = null;
String logTag = null;
+ long eps = 0;
try {
- long eps = sw.elapsed(TimeUnit.MILLISECONDS);
+ eps = sw.elapsed(TimeUnit.MILLISECONDS);
if (eps > 10) {
LOGGER.warn("Warning: instanceExecutorPool took " + eps + "ms to start search.");
if (eps > instanceFuturePoolWaitTimeout) {
@@ -244,12 +250,19 @@ public LindenResult apply() {
logTag = "instanceExceptionalSearch";
} finally {
metricsManager.time(sw.elapsed(TimeUnit.NANOSECONDS), logTag);
- result.setCost((int) sw.elapsed(TimeUnit.MILLISECONDS));
+ long cost = sw.elapsed(TimeUnit.MILLISECONDS);
+ result.setCost((int)cost);
if (result.isSuccess()) {
- LOGGER.info("Instance search request succeeded, request: {}, hits: {}, cost: {} ms.", request,
- result.getHitsSize(), result.getCost());
+ if (cost >= slowQueryThresholdMillis) {
+ SLOW_LOGGER.warn("Slow request: {}, totalHits: {}, waits: {} ms , cost: {} ms.", request.getOriginQuery(),
+ result.getTotalHits(), eps, result.getCost());
+ } else {
+ LOGGER.info("Instance search request succeeded, request: {}, hits: {}, cost: {} ms.",
+ request.getOriginQuery(),
+ result.getHitsSize(), result.getCost());
+ }
} else {
- LOGGER.error("Instance search request failed, request: {}, error: {}, cost: {} ms.", request,
+ LOGGER.error("Instance search request failed, request: {}, error: {}, cost: {} ms.", request.getOriginQuery(),
result.getError(), result.getCost());
}
return result;
@@ -350,7 +363,9 @@ public LindenResult apply() {
}
LindenRequest lindenRequest = bqlCompiler.compile(bql);
if (lindenRequest.isSetSearchRequest()) {
- result = lindenCore.search(lindenRequest.getSearchRequest());
+ LindenSearchRequest searchRequest = lindenRequest.getSearchRequest();
+ searchRequest.setOriginQuery(bql);
+ result = lindenCore.search(searchRequest);
if (result.isSuccess()) {
logTag = "singleInstanceSearch";
} else {
@@ -445,7 +460,9 @@ public LindenResult apply() {
}
LindenRequest request = bqlCompiler.compile(bql);
if (request.isSetSearchRequest()) {
- result = lindenCluster.search(request.getSearchRequest());
+ LindenSearchRequest searchRequest = request.getSearchRequest();
+ searchRequest.setOriginQuery(bql);
+ result = lindenCluster.search(searchRequest);
if (result.isSuccess()) {
logTag = "search";
} else {
@@ -542,7 +559,9 @@ public LindenResult apply() {
}
LindenRequest request = bqlCompiler.compile(bql);
if (request.isSetSearchRequest()) {
- result = lindenCluster.search(request.getSearchRequest());
+ LindenSearchRequest searchRequest = request.getSearchRequest();
+ searchRequest.setOriginQuery(bql);
+ result = lindenCluster.search(searchRequest);
if (result.isSuccess()) {
logTag = "search";
} else {
diff --git a/linden-core/src/test/java/com/xiaomi/linden/lucene/query/flexiblequery/TestFlexibleQuery.java b/linden-core/src/test/java/com/xiaomi/linden/lucene/query/flexiblequery/TestFlexibleQuery.java
index 43f818b..f4dd6bf 100644
--- a/linden-core/src/test/java/com/xiaomi/linden/lucene/query/flexiblequery/TestFlexibleQuery.java
+++ b/linden-core/src/test/java/com/xiaomi/linden/lucene/query/flexiblequery/TestFlexibleQuery.java
@@ -185,15 +185,15 @@ public void testBasic() throws IOException {
+ " int continuousMatches = 0;\n"
+ " for (int i = 0; i < getFieldLength(); ++i) {\n"
+ " int lastMatechedTermIdx = Integer.MIN_VALUE;\n"
- + " List lastPositions = null;\n"
- + " List curPositions;\n"
+ + " int[] lastPositions = null;\n"
+ + " int[] curPositions;\n"
+ " for (int j = 0; j < getTermLength(); ++j) {\n"
+ " if (isMatched(i, j)) {\n"
+ " curPositions = positions(i, j);\n"
+ " if (lastMatechedTermIdx + 1 == j) {\n"
- + " for (int ii = 0; ii < lastPositions.size(); ++ii)\n"
- + " for (int jj = 0; jj < curPositions.size(); ++jj) {\n"
- + " if (lastPositions.get(ii) + 1 == curPositions.get(jj)) {\n"
+ + " for (int ii = 0; ii < lastPositions.length; ++ii)\n"
+ + " for (int jj = 0; jj < curPositions.length; ++jj) {\n"
+ + " if (lastPositions[ii] + 1 == curPositions[jj]) {\n"
+ " ++continuousMatches;\n"
+ " }\n"
+ " }\n"
@@ -229,15 +229,15 @@ public void testBasic() throws IOException {
+ " int continuousMatches = 0;\n"
+ " float fieldScore = 0f;\n"
+ " int lastMatechedTermIdx = Integer.MIN_VALUE;\n"
- + " List lastPositions = null;\n"
- + " List curPositions;\n"
+ + " int[] lastPositions = null;\n"
+ + " int[] curPositions;\n"
+ " for (int j = 0; j < getTermLength(); ++j) {\n"
+ " if (isMatched(i, j)) {\n"
+ " curPositions = positions(i, j);\n"
+ " if (lastMatechedTermIdx + 1 == j) {\n"
- + " for (int ii = 0; ii < lastPositions.size(); ++ii)\n"
- + " for (int jj = 0; jj < curPositions.size(); ++jj) {\n"
- + " if (lastPositions.get(ii) + 1 == curPositions.get(jj)) {\n"
+ + " for (int ii = 0; ii < lastPositions.length; ++ii)\n"
+ + " for (int jj = 0; jj < curPositions.length; ++jj) {\n"
+ + " if (lastPositions[ii] + 1 == curPositions[jj]) {\n"
+ " ++continuousMatches;\n"
+ " }\n"
+ " }\n"
diff --git a/linden-thrift/src/main/thrift/LindenRequest.thrift b/linden-thrift/src/main/thrift/LindenRequest.thrift
index 3e56ec0..89ea4c7 100644
--- a/linden-thrift/src/main/thrift/LindenRequest.thrift
+++ b/linden-thrift/src/main/thrift/LindenRequest.thrift
@@ -305,6 +305,7 @@ struct LindenSearchRequest {
14: optional list sourceFields,
15: optional list indexNames,
16: optional GroupParam groupParam,
+ 17: optional string originQuery,
}
struct LindenDeleteRequest {