Add traces search (#56)

diff --git a/.gitmodules b/.gitmodules
index 5ba3c21..3405629 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,3 @@
 [submodule "query-protocol"]
 	path = query-protocol
-	url = http://github.com/apache/skywalking-query-protocol/
+	url = http://github.com/apache/skywalking-query-protocol/
\ No newline at end of file
diff --git a/README.md b/README.md
index 3655fa9..298e680 100644
--- a/README.md
+++ b/README.md
@@ -263,9 +263,24 @@
 
 </details>
 
-### `dashboard`
+### `trace ls`
 
-#### `dashboard global-metrics`
+<details>
+
+<summary>trace ls</summary>
+
+| argument | description | default |
+| :--- | :--- | :--- |
+| `--trace-id` | the trace id whose spans are to displayed |  |
+| `--service-id` | the service id whose trace are to displayed |  |
+| `--service-instance-id` | the service instance id whose trace are to displayed |  |
+| `--tags` | Only tags defined in the core/default/searchableTagKeys are searchable. Check more details on the Configuration Vocabulary page | See [Configuration Vocabulary page](https://github.com/apache/skywalking/blob/master/docs/en/setup/backend/configuration-vocabulary.md) |
+| `--start` | See [Common options](#common-options) | See [Common options](#common-options) |
+| `--end` | See [Common options](#common-options) | See [Common options](#common-options) |
+
+</details>
+
+### `dashboard`
 
 <details>
 
@@ -275,25 +290,13 @@
 
 | argument | description | default |
 | :--- | :--- | :--- |
-| `--template` | The template file to customize how to display information | `templates/Dashboard.Global.json` |
+| `--template` | the template file to customize how to display information | `templates/Dashboard.Global.json` |
 
 You can imitate the content of [the default template file](example/Dashboard.Global.json) to customize the dashboard.
 
 </details>
 
-#### `dashboard global`
 
-<details>
-
-<summary>dashboard global [--template=template]</summary>
-
-`dashboard global` displays global metrics, global response latency and global heat map in the form of a dashboard.
-
-| argument | description | default |
-| :--- | :--- | :--- |
-| `--template` | The template file to customize how to display information | `templates/Dashboard.Global.json` |
-
-</details>
 
 ### `checkHealth`
 
@@ -567,6 +570,16 @@
 
 <details>
 
+<summary>Display the traces</summary>
+
+```shell
+$ ./bin/swctl --display graph trace ls --start='2020-08-13 1754' --end='2020-08-20 2020'  --tags='http.method=POST'
+```
+
+</details>
+
+<details>
+
 <summary>Automatically convert to server side timezone</summary>
 
 if your backend nodes are deployed in docker and the timezone is UTC, you may not want to convert your timezone to UTC every time you type a command, `--timezone` comes to your rescue.
diff --git a/assets/graphqls/trace/Traces.graphql b/assets/graphqls/trace/Traces.graphql
new file mode 100644
index 0000000..ef91477
--- /dev/null
+++ b/assets/graphqls/trace/Traces.graphql
@@ -0,0 +1,30 @@
+# Licensed to 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. Apache Software Foundation (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.
+
+query ($condition: TraceQueryCondition!){
+    result: queryBasicTraces(condition: $condition){
+        total
+        traces {
+            segmentId
+            endpointNames
+            duration
+            start
+            isError
+            traceIds
+        }
+    }
+}
\ No newline at end of file
diff --git a/commands/trace/list.go b/commands/trace/list.go
index f23845e..0d875c7 100644
--- a/commands/trace/list.go
+++ b/commands/trace/list.go
@@ -17,13 +17,106 @@
 
 package trace
 
-import "github.com/urfave/cli"
+import (
+	"strings"
+
+	"github.com/apache/skywalking-cli/display/displayable"
+
+	"github.com/apache/skywalking-cli/commands/interceptor"
+
+	"github.com/urfave/cli"
+
+	"github.com/apache/skywalking-cli/commands/flags"
+	"github.com/apache/skywalking-cli/commands/model"
+	"github.com/apache/skywalking-cli/display"
+
+	"github.com/apache/skywalking-cli/graphql/schema"
+	"github.com/apache/skywalking-cli/graphql/trace"
+)
+
+const DefaultPageSize = 15
 
 var ListCommand = cli.Command{
 	Name:      "list",
 	ShortName: "ls",
 	Usage:     "query traces",
+	Flags: flags.Flags(
+		flags.DurationFlags,
+		[]cli.Flag{
+			cli.StringFlag{
+				Name:     "service-id",
+				Usage:    "service id",
+				Required: false,
+			},
+			cli.StringFlag{
+				Name:     "service-instance-id",
+				Usage:    "service instance id",
+				Required: false,
+			},
+			cli.StringFlag{
+				Name:     "trace-id",
+				Usage:    "trace id",
+				Required: false,
+			},
+			cli.StringFlag{
+				Name:     "tags",
+				Usage:    "key=value,key=value",
+				Required: false,
+			},
+		},
+	),
+	Before: interceptor.BeforeChain([]cli.BeforeFunc{
+		interceptor.TimezoneInterceptor,
+		interceptor.DurationInterceptor,
+	}),
 	Action: func(ctx *cli.Context) error {
-		return nil
+
+		start := ctx.String("start")
+		end := ctx.String("end")
+		step := ctx.Generic("step")
+
+		duration := schema.Duration{
+			Start: start,
+			End:   end,
+			Step:  step.(*model.StepEnumValue).Selected,
+		}
+		serviceID := ctx.String("service-id")
+		serviceInstanceID := ctx.String("service-instance-id")
+		traceID := ctx.String("trace-id")
+		tagStr := ctx.String("tags")
+		var tags []*schema.SpanTag = nil
+		if tagStr != "" {
+			tagArr := strings.Split(tagStr, ",")
+			for _, tag := range tagArr {
+				kv := strings.Split(tag, "=")
+				tags = append(tags, &schema.SpanTag{Key: kv[0], Value: &kv[1]})
+			}
+		}
+		pageNum := 1
+		needTotal := true
+
+		paging := schema.Pagination{
+			PageNum:   &pageNum,
+			PageSize:  DefaultPageSize,
+			NeedTotal: &needTotal,
+		}
+
+		condition := &schema.TraceQueryCondition{
+			ServiceID:         &serviceID,
+			ServiceInstanceID: &serviceInstanceID,
+			TraceID:           &traceID,
+			EndpointID:        nil,
+			EndpointName:      nil,
+			QueryDuration:     &duration,
+			MinTraceDuration:  nil,
+			MaxTraceDuration:  nil,
+			TraceState:        schema.TraceStateAll,
+			QueryOrder:        schema.QueryOrderByDuration,
+			Tags:              tags,
+			Paging:            &paging,
+		}
+		traces := trace.Traces(ctx, condition)
+
+		return display.Display(ctx, &displayable.Displayable{Data: traces, Condition: condition})
 	},
 }
diff --git a/display/displayable/displayable.go b/display/displayable/displayable.go
index 12ca7d2..d4678f4 100644
--- a/display/displayable/displayable.go
+++ b/display/displayable/displayable.go
@@ -20,7 +20,8 @@
 import "github.com/apache/skywalking-cli/graphql/schema"
 
 type Displayable struct {
-	Data     interface{}
-	Duration schema.Duration
-	Title    string
+	Data      interface{}
+	Condition interface{}
+	Duration  schema.Duration
+	Title     string
 }
diff --git a/display/graph/graph.go b/display/graph/graph.go
index db68a16..ddc37da 100644
--- a/display/graph/graph.go
+++ b/display/graph/graph.go
@@ -40,6 +40,7 @@
 	LinearMetrics      = map[string]float64
 	MultiLinearMetrics = []LinearMetrics
 	Trace              = schema.Trace
+	TraceBrief         = schema.TraceBrief
 	GlobalMetrics      = [][]*schema.SelectedRecord
 	GlobalData         = dashboard.GlobalData
 )
@@ -49,6 +50,7 @@
 	LinearMetricsType      = reflect.TypeOf(LinearMetrics{})
 	MultiLinearMetricsType = reflect.TypeOf(MultiLinearMetrics{})
 	TraceType              = reflect.TypeOf(Trace{})
+	TraceBriefType         = reflect.TypeOf(TraceBrief{})
 	GlobalMetricsType      = reflect.TypeOf(GlobalMetrics{})
 	GlobalDataType         = reflect.TypeOf(&GlobalData{})
 )
@@ -69,6 +71,9 @@
 	case TraceType:
 		return tree.Display(tree.Adapt(data.(Trace)))
 
+	case TraceBriefType:
+		return tree.DisplayList(ctx, displayable)
+
 	case GlobalMetricsType:
 		return gauge.Display(ctx, data.(GlobalMetrics))
 
diff --git a/display/graph/tree/adapter.go b/display/graph/tree/adapter.go
index 9c33c32..e06c7fa 100644
--- a/display/graph/tree/adapter.go
+++ b/display/graph/tree/adapter.go
@@ -25,17 +25,20 @@
 	"github.com/apache/skywalking-cli/util"
 )
 
-func Adapt(trace schema.Trace) []*Node {
+func Adapt(trace schema.Trace) (roots []*Node, serviceNames []string) {
 	all := make(map[string]*Node)
+	set := make(map[string]bool)
 
 	for _, span := range trace.Spans {
+		if !set[span.ServiceCode] {
+			serviceNames = append(serviceNames, span.ServiceCode)
+			set[span.ServiceCode] = true
+		}
 		all[id(span)] = node(span)
 	}
 
 	seen := make(map[string]bool)
 
-	var roots []*Node
-
 	for _, span := range trace.Spans {
 		if isRoot(span) {
 			roots = append(roots, all[id(span)])
@@ -63,7 +66,7 @@
 		}
 	}
 
-	return roots
+	return roots, serviceNames
 }
 
 func isRoot(span *schema.Span) bool {
diff --git a/display/graph/tree/list.go b/display/graph/tree/list.go
new file mode 100644
index 0000000..cb11f34
--- /dev/null
+++ b/display/graph/tree/list.go
@@ -0,0 +1,190 @@
+// Licensed to 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. Apache Software Foundation (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 tree
+
+import (
+	"fmt"
+	"strings"
+
+	d "github.com/apache/skywalking-cli/display/displayable"
+	"github.com/apache/skywalking-cli/graphql/schema"
+	"github.com/apache/skywalking-cli/graphql/trace"
+
+	ui "github.com/gizak/termui/v3"
+	"github.com/gizak/termui/v3/widgets"
+	"github.com/urfave/cli"
+
+	"github.com/apache/skywalking-cli/logger"
+)
+
+const DefaultPageSize = 15
+const keymap = " Keymap "
+const cc = "<C-c>"
+
+func DisplayList(ctx *cli.Context, displayable *d.Displayable) error {
+	data := displayable.Data.(schema.TraceBrief)
+	condition := displayable.Condition.(*schema.TraceQueryCondition)
+	if err := ui.Init(); err != nil {
+		logger.Log.Fatalf("failed to initialize termui: %v", err)
+	}
+	defer ui.Close()
+
+	list := widgets.NewList()
+	list.TitleStyle.Fg = ui.ColorRed
+	list.TextStyle = ui.NewStyle(ui.ColorYellow)
+	list.WrapText = false
+
+	tree := widgets.NewTree()
+	tree.TextStyle = ui.NewStyle(ui.ColorYellow)
+	tree.WrapText = false
+	tree.TitleStyle.Fg = ui.ColorRed
+
+	help := widgets.NewParagraph()
+	help.WrapText = false
+	help.Title = keymap
+	help.Text = `[k          ](fg:red,mod:bold) Scroll Up
+		[<Up>       ](fg:red,mod:bold) Scroll Up
+		[j          ](fg:red,mod:bold) Scroll Down
+		[<Down>     ](fg:red,mod:bold) Scroll Down
+		[<Ctr-b>    ](fg:red,mod:bold) list Page Up
+		[<Ctr-f>    ](fg:red,mod:bold) list Page Down           
+		[p          ](fg:red,mod:bold) list Page Up
+		[n          ](fg:red,mod:bold) list Page Down
+		[<Ctr-u>    ](fg:red,mod:bold) Scroll Half Page Up
+		[<Ctr-d>    ](fg:red,mod:bold) Scroll Half Page Down
+		[<Home>     ](fg:red,mod:bold) Scroll to Top
+		[<Enter>    ](fg:red,mod:bold) Show Trace
+		[<End>      ](fg:red,mod:bold) Scroll to Bottom
+		[q          ](fg:red,mod:bold) Quit
+		[<Ctr-c>    ](fg:red,mod:bold) Quit
+        `
+	draw(list, tree, help, data, 0, ctx, condition)
+	listenTracesKeyboard(list, tree, data, ctx, help, condition)
+
+	return nil
+}
+
+func draw(list *widgets.List, tree *widgets.Tree, help *widgets.Paragraph, data schema.TraceBrief, showIndex int,
+	ctx *cli.Context, condition *schema.TraceQueryCondition) {
+	x, y := ui.TerminalDimensions()
+
+	if data.Total != 0 {
+		var traceID = data.Traces[showIndex].TraceIds[0]
+		list.Title = fmt.Sprintf("[ %d/%d  %s]", *condition.Paging.PageNum, totalPages(data.Total), traceID)
+		nodes, serviceNames := getNodeData(ctx, traceID)
+		tree.Title = fmt.Sprintf("[%s]", strings.Join(serviceNames, "->"))
+		tree.SetNodes(nodes)
+		list.Rows = rows(data, x/4)
+	} else {
+		noData := "no data"
+		list.Title = noData
+		tree.Title = noData
+	}
+
+	list.SetRect(0, 0, x, y)
+	tree.SetRect(x/4, 0, x, y)
+	help.SetRect(x-x/7, 0, x, y)
+	tree.ExpandAll()
+	ui.Render(list, tree, help)
+}
+func totalPages(total int) int {
+	if total%DefaultPageSize == 0 {
+		return total / DefaultPageSize
+	}
+	return total/DefaultPageSize + 1
+}
+
+func listenTracesKeyboard(list *widgets.List, tree *widgets.Tree, data schema.TraceBrief, ctx *cli.Context,
+	help *widgets.Paragraph, condition *schema.TraceQueryCondition) {
+	uiEvents := ui.PollEvents()
+	for {
+		showIndex := 0
+		e := <-uiEvents
+
+		switch e.ID {
+		case "q", cc:
+			return
+		case "<C-b>", "p":
+			pageNum := *condition.Paging.PageNum
+			if pageNum != 1 {
+				pageNum--
+				condition.Paging.PageNum = &pageNum
+				data = trace.Traces(ctx, condition)
+			}
+		case "<C-f>", "n":
+			pageNum := *condition.Paging.PageNum
+			if pageNum < totalPages(data.Total) {
+				pageNum++
+				condition.Paging.PageNum = &pageNum
+				data = trace.Traces(ctx, condition)
+			}
+		default:
+			if action := listActions(e.ID, list); action != nil {
+				action()
+			}
+			showIndex = list.SelectedRow
+		}
+		draw(list, tree, help, data, showIndex, ctx, condition)
+	}
+}
+func listActions(key string, list *widgets.List) func() {
+	// mostly vim style
+	actions := map[string]func(){
+		"k":      list.ScrollUp,
+		"<Up>":   list.ScrollUp,
+		"j":      list.ScrollDown,
+		"<Down>": list.ScrollDown,
+		"<C-u>":  list.ScrollHalfPageUp,
+		"<C-d>":  list.ScrollHalfPageDown,
+		"<Home>": list.ScrollTop,
+		"G":      list.ScrollBottom,
+		"<End>":  list.ScrollBottom,
+	}
+
+	return actions[key]
+}
+
+func getNodeData(ctx *cli.Context, traceID string) (nodes []*widgets.TreeNode, serviceNames []string) {
+	data := trace.Trace(ctx, traceID)
+	var roots []*Node
+	roots, serviceNames = Adapt(data)
+
+	nodes = make([]*widgets.TreeNode, len(roots))
+	for i := range nodes {
+		nodes[i] = &widgets.TreeNode{}
+	}
+
+	for i, root := range roots {
+		adapt(root, nodes[i])
+	}
+	return nodes, serviceNames
+}
+
+func rows(data schema.TraceBrief, subLen int) []string {
+	var rows []string
+
+	for _, t := range data.Traces {
+		endpointName := t.EndpointNames[0]
+		if len(endpointName) > subLen-3 {
+			endpointName = endpointName[0:subLen-3] + "..."
+		}
+
+		rows = append(rows, fmt.Sprintf("[%s](mod:bold,fg:green) ", endpointName))
+	}
+	return rows
+}
diff --git a/display/graph/tree/tree.go b/display/graph/tree/tree.go
index 5df89ef..aff3bf0 100644
--- a/display/graph/tree/tree.go
+++ b/display/graph/tree/tree.go
@@ -19,6 +19,7 @@
 
 import (
 	"fmt"
+	"strings"
 
 	ui "github.com/gizak/termui/v3"
 	"github.com/gizak/termui/v3/widgets"
@@ -34,7 +35,7 @@
 
 var extra = make(map[*widgets.TreeNode]*Node)
 
-func Display(roots []*Node) error {
+func Display(roots []*Node, serviceNames []string) error {
 	if err := ui.Init(); err != nil {
 		logger.Log.Fatalf("failed to initialize termui: %v", err)
 	}
@@ -62,7 +63,7 @@
 	}
 	tree.WrapText = false
 	tree.SetNodes(nodes)
-	tree.Title = " Press ? to show help "
+	tree.Title = fmt.Sprintf("[ %s ]        [%s]", strings.Join(serviceNames, "->"), " Press ? to show help ")
 	tree.TitleStyle.Modifier = ui.ModifierBold
 	tree.TitleStyle.Fg = ui.ColorRed
 
@@ -78,7 +79,7 @@
 	help := widgets.NewParagraph()
 	help.WrapText = false
 	help.SetRect(x, 0, x, y)
-	help.Title = " Keymap "
+	help.Title = keymap
 	help.Text = `
 		[?          ](fg:red,mod:bold) Toggle this help
 		[k          ](fg:red,mod:bold) Scroll Up
@@ -164,7 +165,7 @@
 		e := <-uiEvents
 
 		switch e.ID {
-		case "q", "<C-c>":
+		case "q", cc:
 			return
 		case "g":
 			if previousKey == "g" {
diff --git a/go.mod b/go.mod
index 6eb95eb..0ef11db 100644
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,7 @@
 go 1.13
 
 require (
-	github.com/99designs/gqlgen v0.11.3 // indirect
+	github.com/99designs/gqlgen v0.12.1 // indirect
 	github.com/gizak/termui/v3 v3.1.0
 	github.com/gobuffalo/packr/v2 v2.8.0
 	github.com/machinebox/graphql v0.2.2
diff --git a/go.sum b/go.sum
index 0cf4386..31323c1 100644
--- a/go.sum
+++ b/go.sum
@@ -1,6 +1,6 @@
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-github.com/99designs/gqlgen v0.11.3 h1:oFSxl1DFS9X///uHV3y6CEfpcXWrDUxVblR4Xib2bs4=
-github.com/99designs/gqlgen v0.11.3/go.mod h1:RgX5GRRdDWNkh4pBrdzNpNPFVsdoUFY2+adM6nb1N+4=
+github.com/99designs/gqlgen v0.12.1 h1:Qfi6HDi6uDxGVKvz5kg8/5iP9YF2XqhwIoBKAt+Nt6M=
+github.com/99designs/gqlgen v0.12.1/go.mod h1:7zdGo6ry9u1YBp/qlb2uxSU5Mt2jQKLcBETQiKk+Bxo=
 github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
@@ -63,13 +63,12 @@
 github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
 github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
 github.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
-github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
 github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
 github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
+github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
 github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
 github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
-github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
 github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
 github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
@@ -104,7 +103,6 @@
 github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
 github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
 github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
-github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007 h1:reVOUXwnhsYv/8UqjvhrMOu5CNT9UapHFLbQ2JcXsmg=
 github.com/matryer/moq v0.0.0-20200106131100-75d0ddfc0007/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=
 github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
 github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
@@ -121,8 +119,6 @@
 github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
 github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
 github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
-github.com/mum4k/termdash v0.10.0 h1:uqM6ePiMf+smecb1tJJeON36o1hREeCfOmLFG0iz4a0=
-github.com/mum4k/termdash v0.10.0/go.mod h1:l3tO+lJi9LZqXRq7cu7h5/8rDIK3AzelSuq2v/KncxI=
 github.com/mum4k/termdash v0.12.1 h1:g3WAT602WIYII6Szhn2KsGoT4PffJZQoA4aAFxEllKc=
 github.com/mum4k/termdash v0.12.1/go.mod h1:haerPCSO0U8pehROAecmuOHDF+2UXw2KaCTxdWooDFE=
 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
@@ -158,6 +154,7 @@
 github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
 github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
 github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
 github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
 github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
@@ -187,10 +184,10 @@
 github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
 github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY=
 github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
-github.com/urfave/cli/v2 v2.1.1 h1:Qt8FeAtxE/vfdrLmR3rxR6JRE0RoVmbXu8+6kZtYU4k=
 github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
-github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e h1:+w0Zm/9gaWpEAyDlU1eKOuk5twTjAjuevXqcJJw8hrg=
 github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U=
+github.com/vektah/gqlparser v1.3.1 h1:8b0IcD3qZKWJQHSzynbDlrtP3IxVydZ2DZepCGofqfU=
+github.com/vektah/gqlparser v1.3.1/go.mod h1:bkVf0FX+Stjg/MHnm8mEyubuaArhNEqfQhF+OTiAL74=
 github.com/vektah/gqlparser/v2 v2.0.1 h1:xgl5abVnsd4hkN9rk65OJID9bfcLSMuTaTcZj777q1o=
 github.com/vektah/gqlparser/v2 v2.0.1/go.mod h1:SyUiHgLATUR8BiYURfTirrTcGpcE+4XkV2se04Px1Ms=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
@@ -271,7 +268,6 @@
 gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
 gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
 gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
diff --git a/graphql/trace/trace.go b/graphql/trace/trace.go
index b09a56f..fab21e7 100644
--- a/graphql/trace/trace.go
+++ b/graphql/trace/trace.go
@@ -36,3 +36,14 @@
 
 	return response["result"]
 }
+
+func Traces(ctx *cli.Context, condition *schema.TraceQueryCondition) schema.TraceBrief {
+	var response map[string]schema.TraceBrief
+
+	request := graphql.NewRequest(assets.Read("graphqls/trace/Traces.graphql"))
+	request.Var("condition", condition)
+
+	client.ExecuteQueryOrFail(ctx, request, &response)
+
+	return response["result"]
+}
diff --git a/query-protocol b/query-protocol
index 563bb51..92f62f1 160000
--- a/query-protocol
+++ b/query-protocol
@@ -1 +1 @@
-Subproject commit 563bb51c71922f017911345d7cd5c62a7ac8995c
+Subproject commit 92f62f13be3a2bf3dfd007ee85c68d54af2c6149