You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2020/08/07 10:04:19 UTC

[skywalking] 01/01: Support tag-based query in ES 6/7

This is an automated email from the ASF dual-hosted git repository.

wusheng pushed a commit to branch tag-query
in repository https://gitbox.apache.org/repos/asf/skywalking.git

commit d9d781ce267cf3f62cf55517fffbb9f174b0b70e
Author: Wu Sheng <wu...@foxmail.com>
AuthorDate: Fri Aug 7 18:03:43 2020 +0800

    Support tag-based query in ES 6/7
---
 .../analyzer/provider/AnalyzerModuleConfig.java    | 10 ++++
 .../analyzer/provider/trace/parser/SpanTags.java   | 19 +++++++
 .../parser/listener/SegmentAnalysisListener.java   | 24 +++++++--
 .../src/main/resources/application.yml             |  1 +
 .../apache/skywalking/oap/server/core/Const.java   |  1 +
 .../analysis/manual/segment/SegmentDispatcher.java |  1 +
 .../analysis/manual/segment/SegmentRecord.java     |  9 ++++
 .../core/analysis/manual/segment/SpanTag.java      | 58 ++++++++++++++++++++++
 .../oap/server/core/query/TraceQueryService.java   |  7 +--
 .../core/query/input/TraceQueryCondition.java      |  3 ++
 .../skywalking/oap/server/core/source/Segment.java |  6 +++
 .../server/core/storage/model/DataTypeMapping.java |  8 ++-
 .../oap/server/core/storage/model/ModelColumn.java |  4 ++
 .../server/core/storage/model/StorageModels.java   |  4 +-
 .../server/core/storage/query/ITraceQueryDAO.java  | 18 +++++--
 .../server/core/storage/model/ModelColumnTest.java |  8 +--
 .../oap/query/graphql/resolver/TraceQuery.java     |  2 +-
 .../src/main/resources/query-protocol              |  2 +-
 .../server/receiver/trace/mock/ServiceAMock.java   |  5 +-
 .../elasticsearch/base/ColumnTypeEsMapping.java    |  8 ++-
 .../elasticsearch/base/StorageEsInstaller.java     |  4 +-
 .../elasticsearch/query/TraceQueryEsDAO.java       | 20 ++++++--
 .../ElasticSearchColumnTypeMappingTestCase.java    | 22 +++++---
 .../elasticsearch7/query/TraceQueryEs7DAO.java     | 19 +++++--
 .../storage/plugin/influxdb/query/TraceQuery.java  |  4 +-
 .../elasticsearch/JaegerTraceQueryEsDAO.java       |  4 +-
 .../plugin/jdbc/h2/dao/H2TraceQueryDAO.java        |  4 +-
 .../elasticsearch/ZipkinTraceQueryEsDAO.java       |  4 +-
 .../profile/exporter/test/ProfileTraceDAO.java     |  4 +-
 29 files changed, 239 insertions(+), 44 deletions(-)

diff --git a/oap-server/analyzer/agent-analyzer/src/main/java/org/apache/skywalking/oap/server/analyzer/provider/AnalyzerModuleConfig.java b/oap-server/analyzer/agent-analyzer/src/main/java/org/apache/skywalking/oap/server/analyzer/provider/AnalyzerModuleConfig.java
index 84d3b6d..1f3f6c4 100644
--- a/oap-server/analyzer/agent-analyzer/src/main/java/org/apache/skywalking/oap/server/analyzer/provider/AnalyzerModuleConfig.java
+++ b/oap-server/analyzer/agent-analyzer/src/main/java/org/apache/skywalking/oap/server/analyzer/provider/AnalyzerModuleConfig.java
@@ -25,6 +25,7 @@ import lombok.Setter;
 import org.apache.skywalking.oap.server.analyzer.provider.trace.DBLatencyThresholdsAndWatcher;
 import org.apache.skywalking.oap.server.analyzer.provider.trace.TraceSampleRateWatcher;
 import org.apache.skywalking.oap.server.analyzer.provider.trace.UninstrumentedGatewaysConfig;
+import org.apache.skywalking.oap.server.analyzer.provider.trace.parser.SpanTags;
 import org.apache.skywalking.oap.server.library.module.ModuleConfig;
 
 public class AnalyzerModuleConfig extends ModuleConfig {
@@ -76,6 +77,15 @@ public class AnalyzerModuleConfig extends ModuleConfig {
     @Getter
     private int maxSlowSQLLength = 2000;
 
+    /**
+     * Define the set of span tag keys, which should be searchable through the GraphQL.
+     *
+     * @since 8.2.0
+     */
+    @Setter
+    @Getter
+    private String searchableTagKeys = SpanTags.DEFAULT_SEARCHABLE_TAG_KEYS;
+
     @Getter
     private final String configPath = "meter-receive-config";
 }
diff --git a/oap-server/analyzer/agent-analyzer/src/main/java/org/apache/skywalking/oap/server/analyzer/provider/trace/parser/SpanTags.java b/oap-server/analyzer/agent-analyzer/src/main/java/org/apache/skywalking/oap/server/analyzer/provider/trace/parser/SpanTags.java
index 982d5e8..f1b30aa 100644
--- a/oap-server/analyzer/agent-analyzer/src/main/java/org/apache/skywalking/oap/server/analyzer/provider/trace/parser/SpanTags.java
+++ b/oap-server/analyzer/agent-analyzer/src/main/java/org/apache/skywalking/oap/server/analyzer/provider/trace/parser/SpanTags.java
@@ -18,6 +18,8 @@
 
 package org.apache.skywalking.oap.server.analyzer.provider.trace.parser;
 
+import org.apache.skywalking.oap.server.core.Const;
+
 /**
  * Reserved keys of the span. The backend analysis the metrics according the existed tags.
  */
@@ -46,4 +48,21 @@ public class SpanTags {
      * </pre>
      */
     public static final String LOGIC_ENDPOINT = "x-le";
+
+    /**
+     * SkyWalking Java Agent provides the recommended tag keys for other language agents or SDKs. This field declare the
+     * recommended keys should be searchable. User could override this through {@link
+     * org.apache.skywalking.oap.server.analyzer.provider.AnalyzerModuleConfig#setSearchableTagKeys(String)} or the
+     * system environment variable defined in the application.yml.
+     */
+    public static final String DEFAULT_SEARCHABLE_TAG_KEYS = String.join(
+        Const.COMMA,
+        "http.method",
+        "status_code",
+        "db.type",
+        "db.instance",
+        "mq.queue",
+        "mq.topic",
+        "mq.broker"
+        );
 }
diff --git a/oap-server/analyzer/agent-analyzer/src/main/java/org/apache/skywalking/oap/server/analyzer/provider/trace/parser/listener/SegmentAnalysisListener.java b/oap-server/analyzer/agent-analyzer/src/main/java/org/apache/skywalking/oap/server/analyzer/provider/trace/parser/listener/SegmentAnalysisListener.java
index b0f3461..46bf21d 100644
--- a/oap-server/analyzer/agent-analyzer/src/main/java/org/apache/skywalking/oap/server/analyzer/provider/trace/parser/listener/SegmentAnalysisListener.java
+++ b/oap-server/analyzer/agent-analyzer/src/main/java/org/apache/skywalking/oap/server/analyzer/provider/trace/parser/listener/SegmentAnalysisListener.java
@@ -18,22 +18,25 @@
 
 package org.apache.skywalking.oap.server.analyzer.provider.trace.parser.listener;
 
+import java.util.Arrays;
+import java.util.List;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.skywalking.apm.network.language.agent.v3.SegmentObject;
 import org.apache.skywalking.apm.network.language.agent.v3.SpanObject;
 import org.apache.skywalking.apm.util.StringUtil;
+import org.apache.skywalking.oap.server.analyzer.provider.AnalyzerModuleConfig;
 import org.apache.skywalking.oap.server.core.Const;
 import org.apache.skywalking.oap.server.core.CoreModule;
 import org.apache.skywalking.oap.server.core.analysis.IDManager;
 import org.apache.skywalking.oap.server.core.analysis.NodeType;
 import org.apache.skywalking.oap.server.core.analysis.TimeBucket;
+import org.apache.skywalking.oap.server.core.analysis.manual.segment.SpanTag;
 import org.apache.skywalking.oap.server.core.config.NamingControl;
 import org.apache.skywalking.oap.server.core.source.Segment;
 import org.apache.skywalking.oap.server.core.source.SourceReceiver;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
 import org.apache.skywalking.oap.server.library.util.BooleanUtils;
-import org.apache.skywalking.oap.server.analyzer.provider.AnalyzerModuleConfig;
 
 /**
  * SegmentSpanListener forwards the segment raw data to the persistence layer with the query required conditions.
@@ -44,6 +47,7 @@ public class SegmentAnalysisListener implements FirstAnalysisListener, EntryAnal
     private final SourceReceiver sourceReceiver;
     private final TraceSegmentSampler sampler;
     private final NamingControl namingControl;
+    private final List<String> searchableTagKeys;
 
     private final Segment segment = new Segment();
     private SAMPLE_STATUS sampleStatus = SAMPLE_STATUS.UNKNOWN;
@@ -96,7 +100,6 @@ public class SegmentAnalysisListener implements FirstAnalysisListener, EntryAnal
             serviceId,
             endpointName
         );
-
     }
 
     @Override
@@ -144,11 +147,21 @@ public class SegmentAnalysisListener implements FirstAnalysisListener, EntryAnal
             if (!isError && span.getIsError()) {
                 isError = true;
             }
+
+            appendSearchableTags(span);
         });
         final long accurateDuration = endTimestamp - startTimestamp;
         duration = accurateDuration > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) accurateDuration;
     }
 
+    private void appendSearchableTags(SpanObject span) {
+        span.getTagsList().forEach(tag -> {
+            if (searchableTagKeys.contains(tag.getKey())) {
+                segment.getTags().add(new SpanTag(tag.getKey(), tag.getValue()));
+            }
+        });
+    }
+
     @Override
     public void build() {
         if (log.isDebugEnabled()) {
@@ -184,7 +197,12 @@ public class SegmentAnalysisListener implements FirstAnalysisListener, EntryAnal
 
         @Override
         public AnalysisListener create(ModuleManager moduleManager, AnalyzerModuleConfig config) {
-            return new SegmentAnalysisListener(sourceReceiver, sampler, namingControl);
+            return new SegmentAnalysisListener(
+                sourceReceiver,
+                sampler,
+                namingControl,
+                Arrays.asList(config.getSearchableTagKeys().split(Const.COMMA))
+            );
         }
     }
 }
diff --git a/oap-server/server-bootstrap/src/main/resources/application.yml b/oap-server/server-bootstrap/src/main/resources/application.yml
index 1bda6a9..70e48f3 100755
--- a/oap-server/server-bootstrap/src/main/resources/application.yml
+++ b/oap-server/server-bootstrap/src/main/resources/application.yml
@@ -163,6 +163,7 @@ agent-analyzer:
   default:
     sampleRate: ${SW_TRACE_SAMPLE_RATE:10000} # The sample rate precision is 1/10000. 10000 means 100% sample in default.
     slowDBAccessThreshold: ${SW_SLOW_DB_THRESHOLD:default:200,mongodb:100} # The slow database access thresholds. Unit ms.
+    searchableTagKeys: ${SW_SEARCHABLE_TAG_KEYS:http.method,status_code,db.type,db.instance,mq.queue,mq.topic,mq.broker}
 
 receiver-sharing-server:
   selector: ${SW_RECEIVER_SHARING_SERVER:default}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/Const.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/Const.java
index e67871b..3592bc8 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/Const.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/Const.java
@@ -27,6 +27,7 @@ public class Const {
     public static final String RELATION_ID_CONNECTOR = "-";
     public static final String RELATION_ID_PARSER_SPLIT = "\\-";
     public static final String LINE = "-";
+    public static final String COMMA = ",";
     public static final String SPACE = " ";
     public static final String KEY_VALUE_SPLIT = ",";
     public static final String ARRAY_SPLIT = "|";
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/segment/SegmentDispatcher.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/segment/SegmentDispatcher.java
index 69f8fab..ec9ced1 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/segment/SegmentDispatcher.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/segment/SegmentDispatcher.java
@@ -40,6 +40,7 @@ public class SegmentDispatcher implements SourceDispatcher<Segment> {
         segment.setDataBinary(source.getDataBinary());
         segment.setTimeBucket(source.getTimeBucket());
         segment.setVersion(source.getVersion());
+        segment.setTags(SpanTag.Util.toStringList(source.getTags()));
 
         RecordStreamProcessor.getInstance().in(segment);
     }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/segment/SegmentRecord.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/segment/SegmentRecord.java
index a8d523c..9ed37dd 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/segment/SegmentRecord.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/segment/SegmentRecord.java
@@ -18,8 +18,10 @@
 
 package org.apache.skywalking.oap.server.core.analysis.manual.segment;
 
+import java.util.ArrayList;
 import java.util.Base64;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import joptsimple.internal.Strings;
 import lombok.Getter;
@@ -53,6 +55,7 @@ public class SegmentRecord extends Record {
     public static final String IS_ERROR = "is_error";
     public static final String DATA_BINARY = "data_binary";
     public static final String VERSION = "version";
+    public static final String TAGS = "tags";
 
     @Setter
     @Getter
@@ -106,6 +109,10 @@ public class SegmentRecord extends Record {
     @Getter
     @Column(columnName = VERSION, storageOnly = true)
     private int version;
+    @Setter
+    @Getter
+    @Column(columnName = TAGS)
+    private List<String> tags = new ArrayList<>();
 
     @Override
     public String id() {
@@ -139,6 +146,7 @@ public class SegmentRecord extends Record {
                 map.put(DATA_BINARY, new String(Base64.getEncoder().encode(storageData.getDataBinary())));
             }
             map.put(VERSION, storageData.getVersion());
+            map.put(TAGS, storageData.getTags());
             return map;
         }
 
@@ -163,6 +171,7 @@ public class SegmentRecord extends Record {
                 record.setDataBinary(Base64.getDecoder().decode((String) dbMap.get(DATA_BINARY)));
             }
             record.setVersion(((Number) dbMap.get(VERSION)).intValue());
+            // Don't read the tags as they has been in the data binary already.
             return record;
         }
     }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/segment/SpanTag.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/segment/SpanTag.java
new file mode 100644
index 0000000..4dc2514
--- /dev/null
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/manual/segment/SpanTag.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.oap.server.core.analysis.manual.segment;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.skywalking.oap.server.library.util.CollectionUtils;
+
+@Getter
+@Setter
+public class SpanTag {
+    private String key;
+    private String value;
+
+    public SpanTag() {
+    }
+
+    public SpanTag(String key, String value) {
+        this.key = key;
+        this.value = value;
+    }
+
+    @Override
+    public String toString() {
+        return key + "=" + value;
+    }
+
+    public static class Util {
+        public static List<String> toStringList(List<SpanTag> list) {
+            if (CollectionUtils.isEmpty(list)) {
+                return Collections.emptyList();
+            }
+            List<String> result = new ArrayList<>(list.size());
+            list.forEach(e -> result.add(e.toString()));
+            return result;
+        }
+    }
+}
+
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/TraceQueryService.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/TraceQueryService.java
index 4fc0c87..1b73ffd 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/TraceQueryService.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/TraceQueryService.java
@@ -27,6 +27,7 @@ import org.apache.skywalking.apm.network.language.agent.v3.SegmentObject;
 import org.apache.skywalking.oap.server.core.Const;
 import org.apache.skywalking.oap.server.core.CoreModule;
 import org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord;
+import org.apache.skywalking.oap.server.core.analysis.manual.segment.SpanTag;
 import org.apache.skywalking.oap.server.core.config.IComponentLibraryCatalogService;
 import org.apache.skywalking.oap.server.core.query.type.KeyValue;
 import org.apache.skywalking.oap.server.core.query.type.LogEntity;
@@ -83,13 +84,13 @@ public class TraceQueryService implements Service {
                                        final QueryOrder queryOrder,
                                        final Pagination paging,
                                        final long startTB,
-                                       final long endTB) throws IOException {
+                                       final long endTB,
+                                       final List<SpanTag> tags) throws IOException {
         PaginationUtils.Page page = PaginationUtils.INSTANCE.exchange(paging);
 
         return getTraceQueryDAO().queryBasicTraces(
             startTB, endTB, minTraceDuration, maxTraceDuration, endpointName, serviceId, serviceInstanceId, endpointId,
-            traceId, page
-                .getLimit(), page.getFrom(), traceState, queryOrder
+            traceId, page.getLimit(), page.getFrom(), traceState, queryOrder, tags
         );
     }
 
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/TraceQueryCondition.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/TraceQueryCondition.java
index 86cfb14..2b6845f 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/TraceQueryCondition.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/input/TraceQueryCondition.java
@@ -18,8 +18,10 @@
 
 package org.apache.skywalking.oap.server.core.query.input;
 
+import java.util.List;
 import lombok.Getter;
 import lombok.Setter;
+import org.apache.skywalking.oap.server.core.analysis.manual.segment.SpanTag;
 import org.apache.skywalking.oap.server.core.query.type.Pagination;
 import org.apache.skywalking.oap.server.core.query.type.QueryOrder;
 import org.apache.skywalking.oap.server.core.query.type.TraceState;
@@ -38,4 +40,5 @@ public class TraceQueryCondition {
     private TraceState traceState;
     private QueryOrder queryOrder;
     private Pagination paging;
+    private List<SpanTag> tags;
 }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/Segment.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/Segment.java
index 2bdec9a..f7b58f5 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/Segment.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/Segment.java
@@ -18,8 +18,11 @@
 
 package org.apache.skywalking.oap.server.core.source;
 
+import java.util.ArrayList;
+import java.util.List;
 import lombok.Getter;
 import lombok.Setter;
+import org.apache.skywalking.oap.server.core.analysis.manual.segment.SpanTag;
 
 import static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.SEGMENT;
 
@@ -72,4 +75,7 @@ public class Segment extends Source {
     @Setter
     @Getter
     private int version;
+    @Setter
+    @Getter
+    private List<SpanTag> tags = new ArrayList<>();
 }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/model/DataTypeMapping.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/model/DataTypeMapping.java
index 4ad3622..1f679de 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/model/DataTypeMapping.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/model/DataTypeMapping.java
@@ -18,7 +18,11 @@
 
 package org.apache.skywalking.oap.server.core.storage.model;
 
-public interface DataTypeMapping {
+import java.lang.reflect.Type;
 
-    String transform(Class<?> type);
+public interface DataTypeMapping {
+    /**
+     * Map the given typd and genericType of the field to the column type.
+     */
+    String transform(Class<?> type, Type genericType);
 }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/model/ModelColumn.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/model/ModelColumn.java
index 7f8c9a0..85db211 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/model/ModelColumn.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/model/ModelColumn.java
@@ -19,6 +19,7 @@
 package org.apache.skywalking.oap.server.core.storage.model;
 
 import com.google.gson.JsonObject;
+import java.lang.reflect.Type;
 import lombok.Getter;
 import org.apache.skywalking.oap.server.core.analysis.metrics.DataTable;
 
@@ -26,18 +27,21 @@ import org.apache.skywalking.oap.server.core.analysis.metrics.DataTable;
 public class ModelColumn {
     private final ColumnName columnName;
     private final Class<?> type;
+    private final Type genericType;
     private final boolean matchQuery;
     private final boolean storageOnly;
     private final int length;
 
     public ModelColumn(ColumnName columnName,
                        Class<?> type,
+                       Type genericType,
                        boolean matchQuery,
                        boolean storageOnly,
                        boolean isValue,
                        int length) {
         this.columnName = columnName;
         this.type = type;
+        this.genericType = genericType;
         this.matchQuery = matchQuery;
 
         /*
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/model/StorageModels.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/model/StorageModels.java
index 6000a93..600dbe9 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/model/StorageModels.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/model/StorageModels.java
@@ -122,8 +122,8 @@ public class StorageModels implements IModelManager, ModelCreator, ModelManipula
                 }
                 modelColumns.add(
                     new ModelColumn(
-                        new ColumnName(modelName, column.columnName()), field.getType(), column.matchQuery(),
-                        column.storageOnly(), column.dataType().isValue(), columnLength
+                        new ColumnName(modelName, column.columnName()), field.getType(), field.getGenericType(),
+                        column.matchQuery(), column.storageOnly(), column.dataType().isValue(), columnLength
                     ));
                 if (log.isDebugEnabled()) {
                     log.debug("The field named {} with the {} type", column.columnName(), field.getType());
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/ITraceQueryDAO.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/ITraceQueryDAO.java
index 3660034..35e48cf 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/ITraceQueryDAO.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/ITraceQueryDAO.java
@@ -21,6 +21,7 @@ package org.apache.skywalking.oap.server.core.storage.query;
 import java.io.IOException;
 import java.util.List;
 import org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord;
+import org.apache.skywalking.oap.server.core.analysis.manual.segment.SpanTag;
 import org.apache.skywalking.oap.server.core.query.type.QueryOrder;
 import org.apache.skywalking.oap.server.core.query.type.Span;
 import org.apache.skywalking.oap.server.core.query.type.TraceBrief;
@@ -29,9 +30,20 @@ import org.apache.skywalking.oap.server.library.module.Service;
 
 public interface ITraceQueryDAO extends Service {
 
-    TraceBrief queryBasicTraces(long startSecondTB, long endSecondTB, long minDuration, long maxDuration,
-        String endpointName, String serviceId, String serviceInstanceId, String endpointId, String traceId, int limit, int from,
-        TraceState traceState, QueryOrder queryOrder) throws IOException;
+    TraceBrief queryBasicTraces(long startSecondTB,
+                                long endSecondTB,
+                                long minDuration,
+                                long maxDuration,
+                                String endpointName,
+                                String serviceId,
+                                String serviceInstanceId,
+                                String endpointId,
+                                String traceId,
+                                int limit,
+                                int from,
+                                TraceState traceState,
+                                QueryOrder queryOrder,
+                                final List<SpanTag> tags) throws IOException;
 
     List<SegmentRecord> queryByTraceId(String traceId) throws IOException;
 
diff --git a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/storage/model/ModelColumnTest.java b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/storage/model/ModelColumnTest.java
index 7c2d0a2..d90bcc5 100644
--- a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/storage/model/ModelColumnTest.java
+++ b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/storage/model/ModelColumnTest.java
@@ -25,20 +25,20 @@ import org.junit.Test;
 public class ModelColumnTest {
     @Test
     public void testColumnDefine() {
-        ModelColumn column = new ModelColumn(new ColumnName("", "abc"), byte[].class, true,
+        ModelColumn column = new ModelColumn(new ColumnName("", "abc"), byte[].class, byte[].class, true,
                                              false, true, 0
         );
         Assert.assertEquals(true, column.isStorageOnly());
         Assert.assertEquals("abc", column.getColumnName().getName());
 
-        column = new ModelColumn(new ColumnName("", "abc"), DataTable.class, true,
+        column = new ModelColumn(new ColumnName("", "abc"), DataTable.class, DataTable.class, true,
                                  false, true, 200
         );
         Assert.assertEquals(true, column.isStorageOnly());
         Assert.assertEquals("abc", column.getColumnName().getName());
         Assert.assertEquals(0, column.getLength());
 
-        column = new ModelColumn(new ColumnName("", "abc"), String.class, true,
+        column = new ModelColumn(new ColumnName("", "abc"), String.class, String.class, true,
                                  false, true, 200
         );
         Assert.assertEquals(false, column.isStorageOnly());
@@ -47,7 +47,7 @@ public class ModelColumnTest {
 
     @Test(expected = IllegalArgumentException.class)
     public void testConflictDefinition() {
-        ModelColumn column = new ModelColumn(new ColumnName("", "abc"), String.class,
+        ModelColumn column = new ModelColumn(new ColumnName("", "abc"), String.class, String.class,
                                              true, true, true, 200
         );
     }
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/TraceQuery.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/TraceQuery.java
index 804334e..d9df534 100644
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/TraceQuery.java
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/TraceQuery.java
@@ -75,7 +75,7 @@ public class TraceQuery implements GraphQLQueryResolver {
 
         return getQueryService().queryBasicTraces(
             condition.getServiceId(), condition.getServiceInstanceId(), endpointId, traceId, endpointName, minDuration,
-            maxDuration, traceState, queryOrder, pagination, startSecondTB, endSecondTB
+            maxDuration, traceState, queryOrder, pagination, startSecondTB, endSecondTB, condition.getTags()
         );
     }
 
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/resources/query-protocol b/oap-server/server-query-plugin/query-graphql-plugin/src/main/resources/query-protocol
index 563bb51..f38def1 160000
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/resources/query-protocol
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/resources/query-protocol
@@ -1 +1 @@
-Subproject commit 563bb51c71922f017911345d7cd5c62a7ac8995c
+Subproject commit f38def1d502327856c1cae7ceb233f3c0c8c8e2a
diff --git a/oap-server/server-receiver-plugin/skywalking-trace-receiver-plugin/src/test/java/org/apache/skywalking/oap/server/receiver/trace/mock/ServiceAMock.java b/oap-server/server-receiver-plugin/skywalking-trace-receiver-plugin/src/test/java/org/apache/skywalking/oap/server/receiver/trace/mock/ServiceAMock.java
index f72ec1b..f6a7124 100644
--- a/oap-server/server-receiver-plugin/skywalking-trace-receiver-plugin/src/test/java/org/apache/skywalking/oap/server/receiver/trace/mock/ServiceAMock.java
+++ b/oap-server/server-receiver-plugin/skywalking-trace-receiver-plugin/src/test/java/org/apache/skywalking/oap/server/receiver/trace/mock/ServiceAMock.java
@@ -19,6 +19,7 @@
 package org.apache.skywalking.oap.server.receiver.trace.mock;
 
 import io.grpc.stub.StreamObserver;
+import org.apache.skywalking.apm.network.common.v3.KeyStringValuePair;
 import org.apache.skywalking.apm.network.language.agent.v3.SegmentObject;
 import org.apache.skywalking.apm.network.language.agent.v3.SpanLayer;
 import org.apache.skywalking.apm.network.language.agent.v3.SpanObject;
@@ -29,7 +30,7 @@ class ServiceAMock {
     public static String SERVICE_NAME = "mock_a_service";
     public static String SERVICE_INSTANCE_NAME = "mock_a_service_instance";
 
-    static String REST_ENDPOINT = "/dubbox-case/case/dubbox-rest";
+    static String REST_ENDPOINT = "/dubbox-case/case/dubbox-rest/404-test";
     static String DUBBO_ENDPOINT = "org.skywaking.apm.testcase.dubbo.services.GreetService.doBusiness()";
     static String DUBBO_ADDRESS = "DubboIPAddress:1000";
 
@@ -62,6 +63,8 @@ class ServiceAMock {
         span.setComponentId(ComponentsDefine.TOMCAT.getId());
         span.setOperationName(REST_ENDPOINT);
         span.setIsError(false);
+        span.addTags(KeyStringValuePair.newBuilder().setKey("http.method").setValue("get").build());
+        span.addTags(KeyStringValuePair.newBuilder().setKey("status_code").setValue("404").build());
         return span;
     }
 
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/ColumnTypeEsMapping.java b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/ColumnTypeEsMapping.java
index 7cec27e..6acc3be 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/ColumnTypeEsMapping.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/ColumnTypeEsMapping.java
@@ -19,6 +19,9 @@
 package org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base;
 
 import com.google.gson.JsonObject;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.List;
 import org.apache.skywalking.oap.server.core.analysis.NodeType;
 import org.apache.skywalking.oap.server.core.storage.model.DataTypeMapping;
 import org.apache.skywalking.oap.server.core.storage.type.StorageDataComplexObject;
@@ -26,7 +29,7 @@ import org.apache.skywalking.oap.server.core.storage.type.StorageDataComplexObje
 public class ColumnTypeEsMapping implements DataTypeMapping {
 
     @Override
-    public String transform(Class<?> type) {
+    public String transform(Class<?> type, Type genericType) {
         if (Integer.class.equals(type) || int.class.equals(type) || NodeType.class.equals(type)) {
             return "integer";
         } else if (Long.class.equals(type) || long.class.equals(type)) {
@@ -41,6 +44,9 @@ public class ColumnTypeEsMapping implements DataTypeMapping {
             return "binary";
         } else if (JsonObject.class.equals(type)) {
             return "text";
+        } else if (List.class.isAssignableFrom(type)) {
+            final Type elementType = ((ParameterizedType) genericType).getActualTypeArguments()[0];
+            return transform((Class<?>) elementType, elementType);
         } else {
             throw new IllegalArgumentException("Unsupported data type: " + type.getName());
         }
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/StorageEsInstaller.java b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/StorageEsInstaller.java
index 143d095..9dc331b 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/StorageEsInstaller.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/StorageEsInstaller.java
@@ -133,7 +133,7 @@ public class StorageEsInstaller extends ModelInstaller {
                 String matchCName = MatchCNameBuilder.INSTANCE.build(columnDefine.getColumnName().getName());
 
                 Map<String, Object> originalColumn = new HashMap<>();
-                originalColumn.put("type", columnTypeEsMapping.transform(columnDefine.getType()));
+                originalColumn.put("type", columnTypeEsMapping.transform(columnDefine.getType(), columnDefine.getGenericType()));
                 originalColumn.put("copy_to", matchCName);
                 properties.put(columnDefine.getColumnName().getName(), originalColumn);
 
@@ -143,7 +143,7 @@ public class StorageEsInstaller extends ModelInstaller {
                 properties.put(matchCName, matchColumn);
             } else {
                 Map<String, Object> column = new HashMap<>();
-                column.put("type", columnTypeEsMapping.transform(columnDefine.getType()));
+                column.put("type", columnTypeEsMapping.transform(columnDefine.getType(), columnDefine.getGenericType()));
                 if (columnDefine.isStorageOnly()) {
                     column.put("index", false);
                 }
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/TraceQueryEsDAO.java b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/TraceQueryEsDAO.java
index 192be91..047be7a 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/TraceQueryEsDAO.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/TraceQueryEsDAO.java
@@ -26,6 +26,7 @@ import java.util.Collections;
 import java.util.List;
 import org.apache.skywalking.apm.util.StringUtil;
 import org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord;
+import org.apache.skywalking.oap.server.core.analysis.manual.segment.SpanTag;
 import org.apache.skywalking.oap.server.core.query.type.BasicTrace;
 import org.apache.skywalking.oap.server.core.query.type.QueryOrder;
 import org.apache.skywalking.oap.server.core.query.type.Span;
@@ -34,6 +35,7 @@ import org.apache.skywalking.oap.server.core.query.type.TraceState;
 import org.apache.skywalking.oap.server.core.storage.query.ITraceQueryDAO;
 import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
 import org.apache.skywalking.oap.server.library.util.BooleanUtils;
+import org.apache.skywalking.oap.server.library.util.CollectionUtils;
 import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.EsDAO;
 import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.MatchCNameBuilder;
 import org.elasticsearch.action.search.SearchResponse;
@@ -67,7 +69,8 @@ public class TraceQueryEsDAO extends EsDAO implements ITraceQueryDAO {
                                        int limit,
                                        int from,
                                        TraceState traceState,
-                                       QueryOrder queryOrder) throws IOException {
+                                       QueryOrder queryOrder,
+                                       final List<SpanTag> tags) throws IOException {
         SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
 
         BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
@@ -120,6 +123,13 @@ public class TraceQueryEsDAO extends EsDAO implements ITraceQueryDAO {
                 sourceBuilder.sort(SegmentRecord.LATENCY, SortOrder.DESC);
                 break;
         }
+        if (CollectionUtils.isNotEmpty(tags)) {
+            BoolQueryBuilder tagMatchQuery = QueryBuilders.boolQuery();
+            tags.forEach(tag -> {
+                tagMatchQuery.must(QueryBuilders.termQuery(SegmentRecord.TAGS, tag.toString()));
+            });
+            mustQueryList.add(tagMatchQuery);
+        }
         sourceBuilder.size(limit);
         sourceBuilder.from(from);
 
@@ -135,9 +145,11 @@ public class TraceQueryEsDAO extends EsDAO implements ITraceQueryDAO {
             basicTrace.setStart(String.valueOf(searchHit.getSourceAsMap().get(SegmentRecord.START_TIME)));
             basicTrace.getEndpointNames().add((String) searchHit.getSourceAsMap().get(SegmentRecord.ENDPOINT_NAME));
             basicTrace.setDuration(((Number) searchHit.getSourceAsMap().get(SegmentRecord.LATENCY)).intValue());
-            basicTrace.setError(BooleanUtils.valueToBoolean(((Number) searchHit.getSourceAsMap()
-                                                                               .get(
-                                                                                   SegmentRecord.IS_ERROR)).intValue()));
+            basicTrace.setError(
+                BooleanUtils.valueToBoolean(
+                    ((Number) searchHit.getSourceAsMap().get(SegmentRecord.IS_ERROR)).intValue()
+                )
+            );
             basicTrace.getTraceIds().add((String) searchHit.getSourceAsMap().get(SegmentRecord.TRACE_ID));
             traceBrief.getTraces().add(basicTrace);
         }
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/test/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/ElasticSearchColumnTypeMappingTestCase.java b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/test/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/ElasticSearchColumnTypeMappingTestCase.java
index 807a7b8..ae1ecc7 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/test/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/ElasticSearchColumnTypeMappingTestCase.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/test/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/base/ElasticSearchColumnTypeMappingTestCase.java
@@ -18,24 +18,30 @@
 
 package org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base;
 
+import java.lang.reflect.Type;
+import java.util.List;
 import org.junit.Assert;
 import org.junit.Test;
 
 public class ElasticSearchColumnTypeMappingTestCase {
+    public List<String> a;
 
     @Test
-    public void test() {
+    public void test() throws NoSuchFieldException {
         ColumnTypeEsMapping mapping = new ColumnTypeEsMapping();
 
-        Assert.assertEquals("integer", mapping.transform(int.class));
-        Assert.assertEquals("integer", mapping.transform(Integer.class));
+        Assert.assertEquals("integer", mapping.transform(int.class, int.class));
+        Assert.assertEquals("integer", mapping.transform(Integer.class, Integer.class));
 
-        Assert.assertEquals("long", mapping.transform(long.class));
-        Assert.assertEquals("long", mapping.transform(Long.class));
+        Assert.assertEquals("long", mapping.transform(long.class, long.class));
+        Assert.assertEquals("long", mapping.transform(Long.class, Long.class));
 
-        Assert.assertEquals("double", mapping.transform(double.class));
-        Assert.assertEquals("double", mapping.transform(Double.class));
+        Assert.assertEquals("double", mapping.transform(double.class, double.class));
+        Assert.assertEquals("double", mapping.transform(Double.class, Double.class));
 
-        Assert.assertEquals("keyword", mapping.transform(String.class));
+        Assert.assertEquals("keyword", mapping.transform(String.class, String.class));
+
+        final Type listFieldType = this.getClass().getField("a").getGenericType();
+        Assert.assertEquals("keyword", mapping.transform(List.class, listFieldType));
     }
 }
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/TraceQueryEs7DAO.java b/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/TraceQueryEs7DAO.java
index c78628d..2077fa9 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/TraceQueryEs7DAO.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch7-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch7/query/TraceQueryEs7DAO.java
@@ -23,12 +23,14 @@ import java.io.IOException;
 import java.util.List;
 import org.apache.skywalking.apm.util.StringUtil;
 import org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord;
+import org.apache.skywalking.oap.server.core.analysis.manual.segment.SpanTag;
 import org.apache.skywalking.oap.server.core.query.type.BasicTrace;
 import org.apache.skywalking.oap.server.core.query.type.QueryOrder;
 import org.apache.skywalking.oap.server.core.query.type.TraceBrief;
 import org.apache.skywalking.oap.server.core.query.type.TraceState;
 import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
 import org.apache.skywalking.oap.server.library.util.BooleanUtils;
+import org.apache.skywalking.oap.server.library.util.CollectionUtils;
 import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.MatchCNameBuilder;
 import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.TraceQueryEsDAO;
 import org.elasticsearch.action.search.SearchResponse;
@@ -59,7 +61,8 @@ public class TraceQueryEs7DAO extends TraceQueryEsDAO {
                                        int limit,
                                        int from,
                                        TraceState traceState,
-                                       QueryOrder queryOrder) throws IOException {
+                                       QueryOrder queryOrder,
+                                       final List<SpanTag> tags) throws IOException {
         SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
 
         BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
@@ -112,6 +115,13 @@ public class TraceQueryEs7DAO extends TraceQueryEsDAO {
                 sourceBuilder.sort(SegmentRecord.LATENCY, SortOrder.DESC);
                 break;
         }
+        if (CollectionUtils.isNotEmpty(tags)) {
+            BoolQueryBuilder tagMatchQuery = QueryBuilders.boolQuery();
+            tags.forEach(tag -> {
+                tagMatchQuery.must(QueryBuilders.termQuery(SegmentRecord.TAGS, tag.toString()));
+            });
+            mustQueryList.add(tagMatchQuery);
+        }
         sourceBuilder.size(limit);
         sourceBuilder.from(from);
 
@@ -127,9 +137,10 @@ public class TraceQueryEs7DAO extends TraceQueryEsDAO {
             basicTrace.setStart(String.valueOf(searchHit.getSourceAsMap().get(SegmentRecord.START_TIME)));
             basicTrace.getEndpointNames().add((String) searchHit.getSourceAsMap().get(SegmentRecord.ENDPOINT_NAME));
             basicTrace.setDuration(((Number) searchHit.getSourceAsMap().get(SegmentRecord.LATENCY)).intValue());
-            basicTrace.setError(BooleanUtils.valueToBoolean(((Number) searchHit.getSourceAsMap()
-                                                                               .get(
-                                                                                   SegmentRecord.IS_ERROR)).intValue()));
+            basicTrace.setError(
+                BooleanUtils.valueToBoolean(
+                    ((Number) searchHit.getSourceAsMap().get(SegmentRecord.IS_ERROR)).intValue())
+            );
             basicTrace.getTraceIds().add((String) searchHit.getSourceAsMap().get(SegmentRecord.TRACE_ID));
             traceBrief.getTraces().add(basicTrace);
         }
diff --git a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/TraceQuery.java b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/TraceQuery.java
index f315082..9d1a479 100644
--- a/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/TraceQuery.java
+++ b/oap-server/server-storage-plugin/storage-influxdb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/influxdb/query/TraceQuery.java
@@ -26,6 +26,7 @@ import java.util.List;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.skywalking.apm.util.StringUtil;
 import org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord;
+import org.apache.skywalking.oap.server.core.analysis.manual.segment.SpanTag;
 import org.apache.skywalking.oap.server.core.query.type.BasicTrace;
 import org.apache.skywalking.oap.server.core.query.type.QueryOrder;
 import org.apache.skywalking.oap.server.core.query.type.Span;
@@ -69,7 +70,8 @@ public class TraceQuery implements ITraceQueryDAO {
                                        int limit,
                                        int from,
                                        TraceState traceState,
-                                       QueryOrder queryOrder)
+                                       QueryOrder queryOrder,
+                                       final List<SpanTag> tags)
         throws IOException {
 
         String orderBy = SegmentRecord.START_TIME;
diff --git a/oap-server/server-storage-plugin/storage-jaeger-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jaeger/elasticsearch/JaegerTraceQueryEsDAO.java b/oap-server/server-storage-plugin/storage-jaeger-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jaeger/elasticsearch/JaegerTraceQueryEsDAO.java
index 6bcd4af..4e8c48f 100644
--- a/oap-server/server-storage-plugin/storage-jaeger-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jaeger/elasticsearch/JaegerTraceQueryEsDAO.java
+++ b/oap-server/server-storage-plugin/storage-jaeger-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jaeger/elasticsearch/JaegerTraceQueryEsDAO.java
@@ -30,6 +30,7 @@ import java.util.List;
 import org.apache.skywalking.apm.util.StringUtil;
 import org.apache.skywalking.oap.server.core.analysis.IDManager;
 import org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord;
+import org.apache.skywalking.oap.server.core.analysis.manual.segment.SpanTag;
 import org.apache.skywalking.oap.server.core.query.type.BasicTrace;
 import org.apache.skywalking.oap.server.core.query.type.KeyValue;
 import org.apache.skywalking.oap.server.core.query.type.LogEntity;
@@ -89,7 +90,8 @@ public class JaegerTraceQueryEsDAO extends EsDAO implements ITraceQueryDAO {
                                        int limit,
                                        int from,
                                        TraceState traceState,
-                                       QueryOrder queryOrder) throws IOException {
+                                       QueryOrder queryOrder,
+                                       final List<SpanTag> tags) throws IOException {
 
         SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
 
diff --git a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2TraceQueryDAO.java b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2TraceQueryDAO.java
index d3ee419..453fd21 100644
--- a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2TraceQueryDAO.java
+++ b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2TraceQueryDAO.java
@@ -29,6 +29,7 @@ import java.util.Collections;
 import java.util.List;
 import org.apache.skywalking.apm.util.StringUtil;
 import org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord;
+import org.apache.skywalking.oap.server.core.analysis.manual.segment.SpanTag;
 import org.apache.skywalking.oap.server.core.query.type.BasicTrace;
 import org.apache.skywalking.oap.server.core.query.type.QueryOrder;
 import org.apache.skywalking.oap.server.core.query.type.Span;
@@ -59,7 +60,8 @@ public class H2TraceQueryDAO implements ITraceQueryDAO {
                                        int limit,
                                        int from,
                                        TraceState traceState,
-                                       QueryOrder queryOrder) throws IOException {
+                                       QueryOrder queryOrder,
+                                       final List<SpanTag> tags) throws IOException {
         StringBuilder sql = new StringBuilder();
         List<Object> parameters = new ArrayList<>(10);
 
diff --git a/oap-server/server-storage-plugin/storage-zipkin-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/zipkin/elasticsearch/ZipkinTraceQueryEsDAO.java b/oap-server/server-storage-plugin/storage-zipkin-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/zipkin/elasticsearch/ZipkinTraceQueryEsDAO.java
index 45f090a..bec545a 100644
--- a/oap-server/server-storage-plugin/storage-zipkin-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/zipkin/elasticsearch/ZipkinTraceQueryEsDAO.java
+++ b/oap-server/server-storage-plugin/storage-zipkin-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/zipkin/elasticsearch/ZipkinTraceQueryEsDAO.java
@@ -27,6 +27,7 @@ import java.util.List;
 import org.apache.skywalking.apm.util.StringUtil;
 import org.apache.skywalking.oap.server.core.analysis.IDManager;
 import org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord;
+import org.apache.skywalking.oap.server.core.analysis.manual.segment.SpanTag;
 import org.apache.skywalking.oap.server.core.query.type.BasicTrace;
 import org.apache.skywalking.oap.server.core.query.type.KeyValue;
 import org.apache.skywalking.oap.server.core.query.type.LogEntity;
@@ -86,7 +87,8 @@ public class ZipkinTraceQueryEsDAO extends EsDAO implements ITraceQueryDAO {
                                        int limit,
                                        int from,
                                        TraceState traceState,
-                                       QueryOrder queryOrder) throws IOException {
+                                       QueryOrder queryOrder,
+                                       final List<SpanTag> tags) throws IOException {
 
         SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
 
diff --git a/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/test/ProfileTraceDAO.java b/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/test/ProfileTraceDAO.java
index fe499d3..7c3a4ba 100644
--- a/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/test/ProfileTraceDAO.java
+++ b/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/test/ProfileTraceDAO.java
@@ -24,6 +24,7 @@ import java.util.List;
 import org.apache.skywalking.apm.network.language.agent.v3.SegmentObject;
 import org.apache.skywalking.apm.network.language.agent.v3.SpanObject;
 import org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord;
+import org.apache.skywalking.oap.server.core.analysis.manual.segment.SpanTag;
 import org.apache.skywalking.oap.server.core.query.type.QueryOrder;
 import org.apache.skywalking.oap.server.core.query.type.Span;
 import org.apache.skywalking.oap.server.core.query.type.TraceBrief;
@@ -50,7 +51,8 @@ public class ProfileTraceDAO implements ITraceQueryDAO {
                                        int limit,
                                        int from,
                                        TraceState traceState,
-                                       QueryOrder queryOrder) throws IOException {
+                                       QueryOrder queryOrder,
+                                       final List<SpanTag> tags) throws IOException {
         return null;
     }