Refactor `metrics` to adopt metrics-v2 protocol (#70)

### Enhancements

- Refactor `metrics single` and `metrics top` to adopt metrics-v2 protocol
- Add error checks for `metrics linear` and `metrics multiple-linear`
- Set the name of `metrics thermodynamic` to default

Closes apache/skywalking#4923
diff --git a/README.md b/README.md
index 4f1623a..62df566 100644
--- a/README.md
+++ b/README.md
@@ -160,12 +160,12 @@
 
 <details>
 
-<summary>metrics linear [--start=start-time] [--end=end-time] --name=metrics-name [--scope=scope-of-metrics]</summary>
+<summary>metrics linear [--start=start-time] [--end=end-time] --name=metrics-name --service=service-name</summary>
 
 | option | description | default |
 | :--- | :--- | :--- |
-| `--name` | Metrics name, defined in [OAL](https://github.com/apache/skywalking/blob/master/oap-server/server-bootstrap/src/main/resources/oal/core.oal), such as `all_p99`, etc. |
-| `--scope` | The scope of metrics, which is consistent with `--name`, such as `All`, `Service`, `ServiceInstance`, `Endpoint`, `ServiceRelation`, `ServiceInstanceRelation` and `EndpointRelation`. |`All`|
+| `--name` | Metrics name, defined in [OAL](https://github.com/apache/skywalking/blob/master/oap-server/server-bootstrap/src/main/resources/oal/core.oal). |
+| `--service` | The name of the service. | "" |
 | `--start` | See [Common options](#common-options) | See [Common options](#common-options) |
 | `--end` | See [Common options](#common-options) | See [Common options](#common-options) |
 
@@ -175,11 +175,12 @@
 
 <details>
 
-<summary>metrics multiple-linear [--start=start-time] [--end=end-time] --name=metrics-name [--num=number-of-linear-metrics]</summary>
+<summary>metrics multiple-linear [--start=start-time] [--end=end-time] --name=metrics-name [--service=service-name] [--num=number-of-linear-metrics]</summary>
 
 | option | description | default |
 | :--- | :--- | :--- |
-| `--name` | Metrics name, defined in [OAL](https://github.com/apache/skywalking/blob/master/oap-server/server-bootstrap/src/main/resources/oal/core.oal), such as `all_p99`, etc. |
+| `--name` | Metrics name that ends with `_percentile`, defined in [OAL](https://github.com/apache/skywalking/blob/master/oap-server/server-bootstrap/src/main/resources/oal/core.oal), such as `all_percentile`, etc. |
+| `--service` | The name of the service, when scope is `All`, no name is required. | "" |
 | `--num` | Number of the linear metrics to fetch | `5` |
 | `--start` | See [Common options](#common-options) | See [Common options](#common-options) |
 | `--end` | See [Common options](#common-options) | See [Common options](#common-options) |
@@ -190,12 +191,12 @@
 
 <details>
 
-<summary>metrics single [--start=start-time] [--end=end-time] --name=metrics-name [--ids=entity-ids]</summary>
+<summary>metrics single [--start=start-time] [--end=end-time] --name=metrics-name --service=service-name</summary>
 
 | option | description | default |
 | :--- | :--- | :--- |
 | `--name` | Metrics name, defined in [OAL](https://github.com/apache/skywalking/blob/master/oap-server/server-bootstrap/src/main/resources/oal/core.oal), such as `service_sla`, etc. |
-| `--ids` | IDs that are required by the metric type, such as service IDs for `service_sla` |
+| `--service` | The name of the service. | "" |
 | `--start` | See [Common options](#common-options) | See [Common options](#common-options) |
 | `--end` | See [Common options](#common-options) | See [Common options](#common-options) |
 
@@ -205,15 +206,16 @@
 
 <details>
 
-<summary>metrics top 3 [--start=start-time] [--end=end-time] --name endpoint_sla [--service-id 3]</summary>
+<summary>metrics top 5 [--start=start-time] [--end=end-time] --name=metrics-name [--service=parent-service] [--order=DES]</summary>
 
 | option | description | default |
 | :--- | :--- | :--- |
+| arguments | The first argument is the number of top entities | `5` |
 | `--name` | Metrics name, defined in [OAL](https://github.com/apache/skywalking/blob/master/oap-server/server-bootstrap/src/main/resources/oal/core.oal), such as `service_sla`, etc. |
-| `--service-id` | service ID that are required by the metric type, such as service IDs for `service_sla` |
+| `--service` | The name of the parent service, could be null if query the global top N. | "" |
+| `--order` | The order of metrics, `DES` or `ASC`. |`DES`|
 | `--start` | See [Common options](#common-options) | See [Common options](#common-options) |
 | `--end` | See [Common options](#common-options) | See [Common options](#common-options) |
-| arguments | the first argument is the number of top entities | `3` |
 
 </details>
 
@@ -221,12 +223,11 @@
 
 <details>
 
-<summary>metrics thermodynamic --name=thermodynamic name [--scope=scope-of-metrics]</summary>
+<summary>metrics thermodynamic [--name=metrics-name]</summary>
 
 | option | description | default |
 | :--- | :--- | :--- |
-| `--name` | Metrics name, defined in [OAL](https://github.com/apache/skywalking/blob/master/oap-server/server-bootstrap/src/main/resources/oal/core.oal), such as `service_sla`, etc. |
-| `--scope` | The scope of metrics, which is consistent with `--name`, such as `All`, `Service`, `ServiceInstance`, `Endpoint`, `ServiceRelation`, `ServiceInstanceRelation` and `EndpointRelation`. |`All`|
+| `--name` | Metrics name that ends with `_heatmap`, defined in [OAL](https://github.com/apache/skywalking/blob/master/oap-server/server-bootstrap/src/main/resources/oal/core.oal), such as `all_heatmap`, etc. | `all_heatmap` |
 | `--start` | See [Common options](#common-options) | See [Common options](#common-options) |
 | `--end` | See [Common options](#common-options) | See [Common options](#common-options) |
 
@@ -376,7 +377,7 @@
 <summary>Query a linear metrics graph for an instance</summary>
 
 ```shell
-$ ./bin/swctl --display=graph metrics linear --name=service_instance_resp_time --scope ServiceInstance
+$ ./bin/swctl --display=graph metrics linear --name=service_instance_resp_time --service "load balancer1.system"
 ┌─────────────────────────────────────────────────────────────────────────────────Press q to quit──────────────────────────────────────────────────────────────────────────────────┐
 │                                                                                                                                                                                  │
 │                                                                                                                                                                                  │
@@ -517,30 +518,30 @@
 <summary>Query the top 5 services whose sla is largest</summary>
 
 ```shell
-$ ./bin/swctl metrics top 5 --name service_sla        
-[{"name":"projectB","id":"2","value":10000},{"name":"projectC","id":"3","value":10000},{"name":"projectA","id":"4","value":10000},{"name":"projectD","id":"5","value":10000}]
+$ ./bin/swctl metrics top 5 --name service_sla
+[{"name":"load balancer1.system","id":"","value":"10000","refId":null},{"name":"load balancer2.system","id":"","value":"10000","refId":null},{"name":"projectB.business-zone","id":"","value":"10000","refId":null},{"name":"projectC.business-zone","id":"","value":"10000","refId":null},{"name":"projectD.business-zone","id":"","value":"10000","refId":null}]
 ```
 
 </details>
 
 <details>
 
-<summary>Query the top 5 instances whose sla is largest, of service (id = 3)</summary>
+<summary>Query the top 5 instances whose sla is largest</summary>
 
 ```shell
-$ ./bin/swctl metrics top 5 --name service_instance_sla --service-id 3        
-[{"name":"projectC-pid:30335@skywalking-server-0002","id":"13","value":10000},{"name":"projectC-pid:22037@skywalking-server-0001","id":"2","value":10000}]
+$ ./bin/swctl metrics top 5 --name service_instance_sla     
+[{"name":"load balancer1.system - load balancer1.system","id":"","value":"10000","refId":null},{"name":"load balancer2.system - load balancer2.system","id":"","value":"10000","refId":null},{"name":"projectA.business-zone - eb38c5efeb874734a7b17de780685c55@192.168.252.12","id":"","value":"10000","refId":null},{"name":"projectB.business-zone - 4e72bad0f2c14381a5657eaaca7f33ba@192.168.252.12","id":"","value":"10000","refId":null},{"name":"projectB.business-zone - 6e0e2e1cc63145859a21fc7bf7f18d2e@192.168.252.13","id":"","value":"10000","refId":null}]
 ```
 
 </details>
 
 <details>
 
-<summary>Query the top 5 endpoints whose sla is largest, of service (id = 3)</summary>
+<summary>Query the top 5 endpoints whose sla is largest</summary>
 
 ```shell
-$ ./bin/swctl metrics top 5 --name endpoint_sla --service-id 3        
-[{"name":"/projectC/{value}","id":"4","value":10000}]
+$ ./bin/swctl metrics top 5 --name endpoint_sla  
+[{"name":"load balancer1.system - /projectA/test","id":"","value":"10000","refId":null},{"name":"load balancer1.system - /","id":"","value":"10000","refId":null},{"name":"load balancer2.system - /projectA/test","id":"","value":"10000","refId":null},{"name":"load balancer2.system - /","id":"","value":"10000","refId":null},{"name":"projectA.business-zone - /projectA/{name}","id":"","value":"10000","refId":null}]
 ```
 
 </details>
@@ -550,12 +551,12 @@
 <summary>Query the overall heat map</summary>
 
 ```shell
-$ ./bin/swctl metrics thermodynamic --name all_heatmap
+$ ./bin/swctl metrics thermodynamic
 {"values":[{"id":"202008290939","values":[473,3,0,0,0,0,0,0,0,0,323,0,4,0,0,0,0,0,0,0,436]},{"id":"202008290940","values":[434,0,0,0,0,0,0,0,0,0,367,0,4,0,0,0,0,0,0,0,427]},{"id":"202008290941","values":[504,0,0,0,0,0,0,0,0,0,410,0,5,0,1,0,0,0,0,0,377]},{"id":"202008290942","values":[445,0,4,0,0,0,0,0,0,0,350,0,0,0,0,0,0,0,0,0,420]},{"id":"202008290943","values":[436,0,1,0,0,0,0,0,0,0,367,0,3,0,0,0,0,0,0,0,404]},{"id":"202008290944","values":[463,0,0,0,0,0,0,0,0,0,353,0,0,0,0,0,0,0,0,0,416]},{"id":"202008290945","values":[496,0,2,3,0,0,0,0,0,0,372,0,4,0,0,0,0,0,0,0,393]},{"id":"202008290946","values":[460,0,4,0,0,0,0,0,0,0,396,0,0,0,0,0,0,0,0,0,408]},{"id":"202008290947","values":[533,0,0,0,0,0,0,0,0,0,400,0,0,0,0,0,0,0,0,0,379]},{"id":"202008290948","values":[539,0,0,0,0,0,0,0,0,0,346,0,1,0,0,0,0,0,0,0,424]},{"id":"202008290949","values":[476,0,0,0,1,0,0,0,0,0,353,0,0,0,3,0,0,0,0,0,435]},{"id":"202008290950","values":[509,0,0,0,0,0,0,0,0,0,371,0,0,0,0,0,0,0,0,0,398]},{"id":"202008290951","values":[478,0,2,0,0,0,0,0,0,0,367,0,10,0,4,0,0,0,0,0,413]},{"id":"202008290952","values":[564,0,4,0,0,0,0,0,0,0,342,0,4,0,0,0,0,0,0,0,414]},{"id":"202008290953","values":[476,0,4,0,0,0,0,0,0,0,448,0,4,0,0,0,0,0,0,0,372]},{"id":"202008290954","values":[502,0,1,0,0,0,0,0,0,0,394,0,7,0,0,0,0,0,0,0,392]},{"id":"202008290955","values":[490,0,2,0,0,0,0,0,0,0,383,0,7,0,0,0,0,0,0,0,407]},{"id":"202008290956","values":[474,0,5,0,0,0,0,0,0,0,397,0,3,0,0,0,0,0,0,0,393]},{"id":"202008290957","values":[484,0,4,0,0,0,0,0,0,0,383,0,0,0,0,0,0,0,0,0,402]},{"id":"202008290958","values":[494,0,8,0,0,0,0,0,0,0,361,0,0,0,0,0,0,0,0,0,416]},{"id":"202008290959","values":[434,0,0,0,0,0,0,0,0,0,354,0,0,0,0,0,0,0,0,0,457]},{"id":"202008291000","values":[507,0,1,0,0,0,0,0,0,0,384,0,7,0,0,0,0,0,0,0,405]},{"id":"202008291001","values":[456,0,2,0,0,0,0,0,0,0,388,0,7,0,1,0,0,0,0,0,412]},{"id":"202008291002","values":[506,0,1,0,0,0,0,0,0,0,385,0,0,0,0,0,0,0,0,0,399]},{"id":"202008291003","values":[494,0,8,0,0,0,0,0,0,0,367,0,0,0,0,0,0,0,0,0,415]},{"id":"202008291004","values":[459,0,1,0,0,0,0,0,0,0,263,0,4,0,0,0,0,0,0,0,474]},{"id":"202008291005","values":[513,0,1,0,0,0,0,0,0,0,371,0,3,0,0,0,0,0,0,0,426]},{"id":"202008291006","values":[462,0,1,0,0,0,0,0,0,0,332,0,0,0,0,0,0,0,0,0,435]},{"id":"202008291007","values":[524,0,4,0,1,0,0,0,0,0,365,0,0,0,3,0,0,0,0,0,427]},{"id":"202008291008","values":[442,0,0,0,0,0,0,0,0,0,304,0,0,0,0,0,0,0,0,0,438]},{"id":"202008291009","values":[584,0,0,0,0,0,0,0,0,0,446,0,0,0,0,0,0,0,0,0,343]}],"buckets":[{"min":"0","max":"100"},{"min":"100","max":"200"},{"min":"200","max":"300"},{"min":"300","max":"400"},{"min":"400","max":"500"},{"min":"500","max":"600"},{"min":"600","max":"700"},{"min":"700","max":"800"},{"min":"800","max":"900"},{"min":"900","max":"1000"},{"min":"1000","max":"1100"},{"min":"1100","max":"1200"},{"min":"1200","max":"1300"},{"min":"1300","max":"1400"},{"min":"1400","max":"1500"},{"min":"1500","max":"1600"},{"min":"1600","max":"1700"},{"min":"1700","max":"1800"},{"min":"1800","max":"1900"},{"min":"1900","max":"2000"},{"min":"2000","max":"infinite+"}]}
 ```
 
 ```shell
-$ ./bin/swctl --display=graph metrics thermodynamic --name all_heatmap 
+$ ./bin/swctl --display=graph metrics thermodynamic
 ```
 
 </details>
diff --git a/assets/graphqls/aggregation/AllEndpointTopN.graphql b/assets/graphqls/aggregation/AllEndpointTopN.graphql
deleted file mode 100644
index a054b10..0000000
--- a/assets/graphqls/aggregation/AllEndpointTopN.graphql
+++ /dev/null
@@ -1,27 +0,0 @@
-# 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 ($name: String!, $topN: Int!, $duration: Duration!, $order: Order!) {
-    result: getAllEndpointTopN(
-        duration: $duration,
-        name: $name,
-        topN: $topN,
-        order: $order
-    ) {
-        id name value
-    }
-}
diff --git a/assets/graphqls/aggregation/AllServiceInstanceTopN.graphql b/assets/graphqls/aggregation/AllServiceInstanceTopN.graphql
deleted file mode 100644
index 0268c60..0000000
--- a/assets/graphqls/aggregation/AllServiceInstanceTopN.graphql
+++ /dev/null
@@ -1,27 +0,0 @@
-# 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 ($name: String!, $topN: Int!, $duration: Duration!, $order: Order!) {
-    result: getAllServiceInstanceTopN(
-        duration: $duration,
-        name: $name,
-        topN: $topN,
-        order: $order
-    ) {
-        id name value
-    }
-}
diff --git a/assets/graphqls/aggregation/EndpointTopN.graphql b/assets/graphqls/aggregation/EndpointTopN.graphql
deleted file mode 100644
index b6e05f6..0000000
--- a/assets/graphqls/aggregation/EndpointTopN.graphql
+++ /dev/null
@@ -1,28 +0,0 @@
-# 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 ($serviceId: ID!, $name: String!, $topN: Int!, $duration: Duration!, $order: Order!) {
-    result: getEndpointTopN(
-        serviceId: $serviceId,
-        duration: $duration,
-        name: $name,
-        topN: $topN,
-        order: $order
-    ) {
-        id name value
-    }
-}
diff --git a/assets/graphqls/aggregation/ServiceInstanceTopN.graphql b/assets/graphqls/aggregation/ServiceInstanceTopN.graphql
deleted file mode 100644
index f643170..0000000
--- a/assets/graphqls/aggregation/ServiceInstanceTopN.graphql
+++ /dev/null
@@ -1,28 +0,0 @@
-# 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 ($serviceId: ID!, $name: String!, $topN: Int!, $duration: Duration!, $order: Order!) {
-    result: getServiceInstanceTopN(
-        serviceId: $serviceId,
-        duration: $duration,
-        name: $name,
-        topN: $topN,
-        order: $order
-    ) {
-        id name value
-    }
-}
diff --git a/assets/graphqls/aggregation/ServiceTopN.graphql b/assets/graphqls/aggregation/ServiceTopN.graphql
deleted file mode 100644
index 754e827..0000000
--- a/assets/graphqls/aggregation/ServiceTopN.graphql
+++ /dev/null
@@ -1,27 +0,0 @@
-# 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 ($name: String!, $topN: Int!, $duration: Duration!, $order: Order!) {
-    result: getServiceTopN(
-        duration: $duration,
-        name: $name,
-        topN: $topN,
-        order: $order
-    ) {
-        id name value
-    }
-}
diff --git a/assets/graphqls/metrics/LinearIntValues.graphql b/assets/graphqls/metrics/LinearIntValues.graphql
deleted file mode 100644
index 6249db2..0000000
--- a/assets/graphqls/metrics/LinearIntValues.graphql
+++ /dev/null
@@ -1,22 +0,0 @@
-# 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 ($metric: MetricCondition!, $duration: Duration!) {
-    result: getLinearIntValues(metric: $metric, duration: $duration) {
-        values { value }
-    }
-}
diff --git a/assets/graphqls/metrics/IntValues.graphql b/assets/graphqls/metrics/MetricsValue.graphql
similarity index 83%
rename from assets/graphqls/metrics/IntValues.graphql
rename to assets/graphqls/metrics/MetricsValue.graphql
index 1138172..9458b04 100644
--- a/assets/graphqls/metrics/IntValues.graphql
+++ b/assets/graphqls/metrics/MetricsValue.graphql
@@ -15,8 +15,6 @@
 # specific language governing permissions and limitations
 # under the License.
 
-query ($metric: BatchMetricConditions!, $duration: Duration!) {
-    result: getValues(metric: $metric, duration: $duration) {
-        values { id value }
-    }
+query ($condition: MetricsCondition!, $duration: Duration!) {
+    result: readMetricsValue(condition: $condition, duration: $duration)
 }
diff --git a/assets/graphqls/dashboard/SortMetrics.graphql b/assets/graphqls/metrics/SortMetrics.graphql
similarity index 100%
rename from assets/graphqls/dashboard/SortMetrics.graphql
rename to assets/graphqls/metrics/SortMetrics.graphql
diff --git a/commands/flags/metrics.go b/commands/flags/metrics.go
new file mode 100644
index 0000000..b1bcfb2
--- /dev/null
+++ b/commands/flags/metrics.go
@@ -0,0 +1,37 @@
+// 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 flags
+
+import (
+	"github.com/urfave/cli"
+)
+
+// MetricsFlags can be reused in several metrics commands.
+var MetricsFlags = []cli.Flag{
+	cli.StringFlag{
+		Name:     "name",
+		Usage:    "metrics `name`, which should be defined in OAL script",
+		Required: true,
+	},
+	cli.StringFlag{
+		Name:     "service",
+		Usage:    "the name of the service",
+		Value:    "",
+		Required: false,
+	},
+}
diff --git a/commands/interceptor/scope.go b/commands/interceptor/scope.go
new file mode 100644
index 0000000..d7c84e8
--- /dev/null
+++ b/commands/interceptor/scope.go
@@ -0,0 +1,45 @@
+// 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 interceptor
+
+import (
+	"strings"
+
+	"github.com/apache/skywalking-cli/graphql/schema"
+)
+
+// ParseScope defines the scope according to name's prefix.
+func ParseScope(name string) schema.Scope {
+	ret := schema.ScopeAll
+
+	if strings.HasPrefix(name, "service_relation") {
+		ret = schema.ScopeServiceRelation
+	} else if strings.HasPrefix(name, "service_instance_relation") {
+		ret = schema.ScopeServiceInstanceRelation
+	} else if strings.HasPrefix(name, "service_instance") {
+		ret = schema.ScopeServiceInstance
+	} else if strings.HasPrefix(name, "service_") {
+		ret = schema.ScopeService
+	} else if strings.HasPrefix(name, "endpoint_relation") {
+		ret = schema.ScopeEndpointRelation
+	} else if strings.HasPrefix(name, "endpoint_") {
+		ret = schema.ScopeEndpoint
+	}
+
+	return ret
+}
diff --git a/commands/interceptor/scope_test.go b/commands/interceptor/scope_test.go
new file mode 100644
index 0000000..8a1d87f
--- /dev/null
+++ b/commands/interceptor/scope_test.go
@@ -0,0 +1,80 @@
+// 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 interceptor
+
+import (
+	"testing"
+
+	"github.com/apache/skywalking-cli/graphql/schema"
+)
+
+func TestParseScope(t *testing.T) {
+	tests := []struct {
+		name        string
+		wantedScope schema.Scope
+	}{
+		{
+			name:        "",
+			wantedScope: schema.ScopeAll,
+		},
+		{
+			name:        "all_percentile",
+			wantedScope: schema.ScopeAll,
+		},
+		{
+			name:        "all_heatmap",
+			wantedScope: schema.ScopeAll,
+		},
+		{
+			name:        "service_resp_time",
+			wantedScope: schema.ScopeService,
+		},
+		{
+			name:        "service_percentile",
+			wantedScope: schema.ScopeService,
+		},
+		{
+			name:        "service_relation_server_percentile ",
+			wantedScope: schema.ScopeServiceRelation,
+		},
+		{
+			name:        "service_instance_relation_client_cpm",
+			wantedScope: schema.ScopeServiceInstanceRelation,
+		},
+		{
+			name:        "service_instance_resp_time",
+			wantedScope: schema.ScopeServiceInstance,
+		},
+		{
+			name:        "endpoint_cpm",
+			wantedScope: schema.ScopeEndpoint,
+		},
+		{
+			name:        "endpoint_relation_resp_time",
+			wantedScope: schema.ScopeEndpointRelation,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			gotScope := ParseScope(tt.name)
+			if gotScope != tt.wantedScope {
+				t.Errorf("ParseScope() got scope = %v, wanted scope %v", gotScope, tt.wantedScope)
+			}
+		})
+	}
+}
diff --git a/commands/metrics/aggregation/topn.go b/commands/metrics/aggregation/topn.go
index ce6c63d..183ec05 100644
--- a/commands/metrics/aggregation/topn.go
+++ b/commands/metrics/aggregation/topn.go
@@ -20,19 +20,16 @@
 import (
 	"fmt"
 	"strconv"
-	"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/interceptor"
 	"github.com/apache/skywalking-cli/commands/model"
 	"github.com/apache/skywalking-cli/display"
-	"github.com/apache/skywalking-cli/graphql/aggregation"
+	"github.com/apache/skywalking-cli/display/displayable"
+	"github.com/apache/skywalking-cli/graphql/metrics"
 	"github.com/apache/skywalking-cli/graphql/schema"
+
+	"github.com/urfave/cli"
 )
 
 var TopN = cli.Command{
@@ -41,12 +38,8 @@
 	ArgsUsage: "<n>",
 	Flags: flags.Flags(
 		flags.DurationFlags,
+		flags.MetricsFlags,
 		[]cli.Flag{
-			cli.StringFlag{
-				Name:     "name",
-				Usage:    "`metrics name`, which should be defined in OAL script",
-				Required: true,
-			},
 			cli.GenericFlag{
 				Name:  "order",
 				Usage: "the `order` by which the top entities are sorted",
@@ -56,11 +49,6 @@
 					Selected: schema.OrderDes,
 				},
 			},
-			cli.StringFlag{
-				Name:     "service-id",
-				Usage:    "the `service id` whose instances/endpoints are to be fetch, if applicable",
-				Required: false,
-			},
 		},
 	),
 	Before: interceptor.BeforeChain([]cli.BeforeFunc{
@@ -68,14 +56,16 @@
 		interceptor.DurationInterceptor,
 	}),
 	Action: func(ctx *cli.Context) error {
-		name := ctx.String("name")
 		start := ctx.String("start")
 		end := ctx.String("end")
 		step := ctx.Generic("step").(*model.StepEnumValue).Selected
-		order := ctx.Generic("order").(*model.OrderEnumValue).Selected
-		serviceID := ctx.String("service-id")
 
+		metricsName := ctx.String("name")
+		normal := true
+		scope := interceptor.ParseScope(metricsName)
+		order := ctx.Generic("order").(*model.OrderEnumValue).Selected
 		topN := 5
+		parentService := ctx.String("service")
 
 		if ctx.NArg() > 0 {
 			nn, err := strconv.Atoi(ctx.Args().First())
@@ -91,23 +81,14 @@
 			Step:  step,
 		}
 
-		var metricsValues []schema.TopNEntity
-
-		if strings.HasPrefix(name, "service_instance") {
-			if serviceID == "" {
-				metricsValues = aggregation.AllServiceInstanceTopN(ctx, name, topN, duration, order)
-			} else {
-				metricsValues = aggregation.ServiceInstanceTopN(ctx, serviceID, name, topN, duration, order)
-			}
-		} else if strings.HasPrefix(name, "endpoint_") {
-			if serviceID == "" {
-				metricsValues = aggregation.AllEndpointTopN(ctx, name, topN, duration, order)
-			} else {
-				metricsValues = aggregation.EndpointTopN(ctx, serviceID, name, topN, duration, order)
-			}
-		} else if strings.HasPrefix(name, "service_") {
-			metricsValues = aggregation.ServiceTopN(ctx, name, topN, duration, order)
-		}
+		metricsValues := metrics.SortMetrics(ctx, schema.TopNCondition{
+			Name:          metricsName,
+			ParentService: &parentService,
+			Normal:        &normal,
+			Scope:         &scope,
+			TopN:          topN,
+			Order:         order,
+		}, duration)
 
 		return display.Display(ctx, &displayable.Displayable{Data: metricsValues})
 	},
diff --git a/commands/metrics/linear/linear-metrics.go b/commands/metrics/linear/linear-metrics.go
index 48cc830..a684781 100644
--- a/commands/metrics/linear/linear-metrics.go
+++ b/commands/metrics/linear/linear-metrics.go
@@ -18,6 +18,8 @@
 package linear
 
 import (
+	"fmt"
+
 	"github.com/apache/skywalking-cli/commands/flags"
 	"github.com/apache/skywalking-cli/commands/interceptor"
 	"github.com/apache/skywalking-cli/commands/model"
@@ -35,23 +37,7 @@
 	Usage: "Query linear metrics defined in backend OAL",
 	Flags: flags.Flags(
 		flags.DurationFlags,
-		[]cli.Flag{
-			cli.StringFlag{
-				Name:     "name",
-				Usage:    "metrics `NAME`, such as `all_p99`",
-				Required: true,
-			},
-			cli.GenericFlag{
-				Name:  "scope",
-				Usage: "the scope of the query, which follows the metrics `name`",
-				Value: &model.ScopeEnumValue{
-					Enum:     schema.AllScope,
-					Default:  schema.ScopeAll,
-					Selected: schema.ScopeAll,
-				},
-				Required: false,
-			},
-		},
+		flags.MetricsFlags,
 	),
 	Before: interceptor.BeforeChain([]cli.BeforeFunc{
 		interceptor.TimezoneInterceptor,
@@ -61,8 +47,18 @@
 		end := ctx.String("end")
 		start := ctx.String("start")
 		step := ctx.Generic("step")
+
 		metricsName := ctx.String("name")
-		scope := ctx.Generic("scope").(*model.ScopeEnumValue).Selected
+		serviceName := ctx.String("service")
+		normal := true
+		scope := interceptor.ParseScope(metricsName)
+
+		if serviceName == "" {
+			return fmt.Errorf("the name of service should be specified")
+		}
+		if scope == schema.ScopeAll {
+			return fmt.Errorf("this command cannot be used to query `All` scope metrics")
+		}
 
 		duration := schema.Duration{
 			Start: start,
@@ -73,7 +69,10 @@
 		metricsValues := metrics.LinearIntValues(ctx, schema.MetricsCondition{
 			Name: metricsName,
 			Entity: &schema.Entity{
-				Scope: scope,
+				Scope:               scope,
+				ServiceName:         &serviceName,
+				Normal:              &normal,
+				ServiceInstanceName: &serviceName,
 			},
 		}, duration)
 
diff --git a/commands/metrics/linear/multiple-linear-metrics.go b/commands/metrics/linear/multiple-linear-metrics.go
index 4036435..9c8bd3b 100644
--- a/commands/metrics/linear/multiple-linear-metrics.go
+++ b/commands/metrics/linear/multiple-linear-metrics.go
@@ -37,12 +37,8 @@
 	Usage: "Query multiple linear metrics defined in backend OAL",
 	Flags: flags.Flags(
 		flags.DurationFlags,
+		flags.MetricsFlags,
 		[]cli.Flag{
-			cli.StringFlag{
-				Name:     "name",
-				Usage:    "metrics `NAME`, such as `all_percentile`",
-				Required: true,
-			},
 			cli.IntFlag{
 				Name:     "num",
 				Usage:    "`num`, the number of linear metrics to query, (default: 5)",
@@ -59,8 +55,16 @@
 		end := ctx.String("end")
 		start := ctx.String("start")
 		step := ctx.Generic("step")
+
 		metricsName := ctx.String("name")
+		serviceName := ctx.String("service")
+		normal := true
 		numOfLinear := ctx.Int("num")
+		scope := interceptor.ParseScope(metricsName)
+
+		if serviceName == "" && scope != schema.ScopeAll {
+			return fmt.Errorf("the name of service should be specified when metrics' scope is not `All`")
+		}
 
 		if numOfLinear > 5 || numOfLinear < 1 {
 			numOfLinear = 5
@@ -80,7 +84,9 @@
 		metricsValuesArray := metrics.MultipleLinearIntValues(ctx, schema.MetricsCondition{
 			Name: metricsName,
 			Entity: &schema.Entity{
-				Scope: schema.ScopeAll,
+				Scope:       scope,
+				ServiceName: &serviceName,
+				Normal:      &normal,
 			},
 		}, labels, duration)
 
diff --git a/commands/metrics/single/single-metrics.go b/commands/metrics/single/single-metrics.go
index 1f710c0..2d92cca 100644
--- a/commands/metrics/single/single-metrics.go
+++ b/commands/metrics/single/single-metrics.go
@@ -18,19 +18,17 @@
 package single
 
 import (
-	"strings"
-
-	"github.com/apache/skywalking-cli/display/displayable"
-
-	"github.com/apache/skywalking-cli/graphql/metrics"
-
-	"github.com/urfave/cli"
+	"fmt"
 
 	"github.com/apache/skywalking-cli/commands/flags"
 	"github.com/apache/skywalking-cli/commands/interceptor"
 	"github.com/apache/skywalking-cli/commands/model"
 	"github.com/apache/skywalking-cli/display"
+	"github.com/apache/skywalking-cli/display/displayable"
+	"github.com/apache/skywalking-cli/graphql/metrics"
 	"github.com/apache/skywalking-cli/graphql/schema"
+
+	"github.com/urfave/cli"
 )
 
 var Command = cli.Command{
@@ -38,18 +36,7 @@
 	Usage: "Query single metrics defined in backend OAL",
 	Flags: flags.Flags(
 		flags.DurationFlags,
-		[]cli.Flag{
-			cli.StringFlag{
-				Name:     "name",
-				Usage:    "metrics `NAME`, which should be defined in OAL script",
-				Required: true,
-			},
-			cli.StringSliceFlag{
-				Name:     "ids",
-				Usage:    "`IDs`, IDs that are required by the given metric type",
-				Required: false,
-			},
-		},
+		flags.MetricsFlags,
 	),
 	Before: interceptor.BeforeChain([]cli.BeforeFunc{
 		interceptor.TimezoneInterceptor,
@@ -59,24 +46,34 @@
 		end := ctx.String("end")
 		start := ctx.String("start")
 		step := ctx.Generic("step")
+
 		metricsName := ctx.String("name")
-		idsString := ctx.StringSlice("ids")
+		serviceName := ctx.String("service")
+		normal := true
+		scope := interceptor.ParseScope(metricsName)
 
-		var ids []string
-
-		for _, id := range idsString {
-			ids = append(ids, strings.Split(id, ",")...)
+		if serviceName == "" {
+			return fmt.Errorf("the name of service should be specified")
+		}
+		if scope == schema.ScopeAll {
+			return fmt.Errorf("this command cannot be used to query `All` scope metrics")
 		}
 
-		metricsValues := metrics.IntValues(ctx, schema.BatchMetricConditions{
-			Name: metricsName,
-			Ids:  ids,
-		}, schema.Duration{
+		duration := schema.Duration{
 			Start: start,
 			End:   end,
 			Step:  step.(*model.StepEnumValue).Selected,
-		})
+		}
 
-		return display.Display(ctx, &displayable.Displayable{Data: metricsValues.Values})
+		metricsValue := metrics.IntValues(ctx, schema.MetricsCondition{
+			Name: metricsName,
+			Entity: &schema.Entity{
+				Scope:       scope,
+				ServiceName: &serviceName,
+				Normal:      &normal,
+			},
+		}, duration)
+
+		return display.Display(ctx, &displayable.Displayable{Data: metricsValue})
 	},
 }
diff --git a/commands/metrics/thermodynamic/thermodynamic.go b/commands/metrics/thermodynamic/thermodynamic.go
index 62268e1..d865422 100644
--- a/commands/metrics/thermodynamic/thermodynamic.go
+++ b/commands/metrics/thermodynamic/thermodynamic.go
@@ -18,16 +18,15 @@
 package thermodynamic
 
 import (
-	"github.com/urfave/cli"
-
-	"github.com/apache/skywalking-cli/display/displayable"
-
 	"github.com/apache/skywalking-cli/commands/flags"
 	"github.com/apache/skywalking-cli/commands/interceptor"
 	"github.com/apache/skywalking-cli/commands/model"
 	"github.com/apache/skywalking-cli/display"
+	"github.com/apache/skywalking-cli/display/displayable"
 	"github.com/apache/skywalking-cli/graphql/metrics"
 	"github.com/apache/skywalking-cli/graphql/schema"
+
+	"github.com/urfave/cli"
 )
 
 var Command = cli.Command{
@@ -40,16 +39,8 @@
 			cli.StringFlag{
 				Name:     "name",
 				Usage:    "metrics `name`, which should be defined in OAL script",
-				Required: true,
-			},
-			cli.GenericFlag{
-				Name:  "scope",
-				Usage: "the scope of the query, which follows the metrics `name`",
-				Value: &model.ScopeEnumValue{
-					Enum:     schema.AllScope,
-					Default:  schema.ScopeAll,
-					Selected: schema.ScopeAll,
-				},
+				Value:    "all_heatmap",
+				Required: false,
 			},
 		},
 	),
@@ -61,8 +52,9 @@
 		end := ctx.String("end")
 		start := ctx.String("start")
 		step := ctx.Generic("step")
+
 		metricsName := ctx.String("name")
-		scope := ctx.Generic("scope").(*model.ScopeEnumValue).Selected
+		scope := interceptor.ParseScope(metricsName)
 
 		duration := schema.Duration{
 			Start: start,
diff --git a/graphql/aggregation/aggregation.go b/graphql/aggregation/aggregation.go
deleted file mode 100644
index 6effe5e..0000000
--- a/graphql/aggregation/aggregation.go
+++ /dev/null
@@ -1,100 +0,0 @@
-// 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 aggregation
-
-import (
-	"github.com/machinebox/graphql"
-	"github.com/urfave/cli"
-
-	"github.com/apache/skywalking-cli/assets"
-
-	"github.com/apache/skywalking-cli/graphql/client"
-	"github.com/apache/skywalking-cli/graphql/schema"
-)
-
-func ServiceTopN(ctx *cli.Context, name string, topN int, duration schema.Duration, order schema.Order) []schema.TopNEntity {
-	var response map[string][]schema.TopNEntity
-
-	request := graphql.NewRequest(assets.Read("graphqls/aggregation/ServiceTopN.graphql"))
-	request.Var("name", name)
-	request.Var("topN", topN)
-	request.Var("duration", duration)
-	request.Var("order", order)
-
-	client.ExecuteQueryOrFail(ctx, request, &response)
-
-	return response["result"]
-}
-
-func AllServiceInstanceTopN(ctx *cli.Context, name string, topN int, duration schema.Duration, order schema.Order) []schema.TopNEntity {
-	var response map[string][]schema.TopNEntity
-
-	request := graphql.NewRequest(assets.Read("graphqls/aggregation/AllServiceInstanceTopN.graphql"))
-	request.Var("name", name)
-	request.Var("topN", topN)
-	request.Var("duration", duration)
-	request.Var("order", order)
-
-	client.ExecuteQueryOrFail(ctx, request, &response)
-
-	return response["result"]
-}
-
-func ServiceInstanceTopN(ctx *cli.Context, serviceID, name string, topN int, duration schema.Duration, order schema.Order) []schema.TopNEntity {
-	var response map[string][]schema.TopNEntity
-
-	request := graphql.NewRequest(assets.Read("graphqls/aggregation/ServiceInstanceTopN.graphql"))
-	request.Var("serviceId", serviceID)
-	request.Var("name", name)
-	request.Var("topN", topN)
-	request.Var("duration", duration)
-	request.Var("order", order)
-
-	client.ExecuteQueryOrFail(ctx, request, &response)
-
-	return response["result"]
-}
-
-func AllEndpointTopN(ctx *cli.Context, name string, topN int, duration schema.Duration, order schema.Order) []schema.TopNEntity {
-	var response map[string][]schema.TopNEntity
-
-	request := graphql.NewRequest(assets.Read("graphqls/aggregation/AllEndpointTopN.graphql"))
-	request.Var("name", name)
-	request.Var("topN", topN)
-	request.Var("duration", duration)
-	request.Var("order", order)
-
-	client.ExecuteQueryOrFail(ctx, request, &response)
-
-	return response["result"]
-}
-
-func EndpointTopN(ctx *cli.Context, serviceID, name string, topN int, duration schema.Duration, order schema.Order) []schema.TopNEntity {
-	var response map[string][]schema.TopNEntity
-
-	request := graphql.NewRequest(assets.Read("graphqls/aggregation/EndpointTopN.graphql"))
-	request.Var("serviceId", serviceID)
-	request.Var("name", name)
-	request.Var("topN", topN)
-	request.Var("duration", duration)
-	request.Var("order", order)
-
-	client.ExecuteQueryOrFail(ctx, request, &response)
-
-	return response["result"]
-}
diff --git a/graphql/dashboard/global.go b/graphql/dashboard/global.go
index 2ea0872..3dbf31a 100644
--- a/graphql/dashboard/global.go
+++ b/graphql/dashboard/global.go
@@ -22,14 +22,12 @@
 	"io/ioutil"
 	"strings"
 
-	"github.com/machinebox/graphql"
 	"github.com/spf13/viper"
 	"github.com/urfave/cli"
 
 	"gopkg.in/yaml.v2"
 
 	"github.com/apache/skywalking-cli/assets"
-	"github.com/apache/skywalking-cli/graphql/client"
 	"github.com/apache/skywalking-cli/graphql/metrics"
 	"github.com/apache/skywalking-cli/graphql/schema"
 	"github.com/apache/skywalking-cli/graphql/utils"
@@ -153,13 +151,7 @@
 	}
 
 	for _, m := range template.Metrics {
-		var response map[string][]*schema.SelectedRecord
-		request := graphql.NewRequest(assets.Read("graphqls/dashboard/SortMetrics.graphql"))
-		request.Var("condition", m.Condition)
-		request.Var("duration", duration)
-
-		client.ExecuteQueryOrFail(ctx, request, &response)
-		ret = append(ret, response["result"])
+		ret = append(ret, metrics.SortMetrics(ctx, m.Condition, duration))
 	}
 
 	return ret
diff --git a/graphql/metrics/metrics.go b/graphql/metrics/metrics.go
index 022779d..174105a 100644
--- a/graphql/metrics/metrics.go
+++ b/graphql/metrics/metrics.go
@@ -18,22 +18,20 @@
 package metrics
 
 import (
+	"github.com/apache/skywalking-cli/assets"
+	"github.com/apache/skywalking-cli/graphql/client"
+	"github.com/apache/skywalking-cli/graphql/schema"
+
 	"github.com/machinebox/graphql"
 	"github.com/urfave/cli"
-
-	"github.com/apache/skywalking-cli/assets"
-
-	"github.com/apache/skywalking-cli/graphql/client"
-
-	"github.com/apache/skywalking-cli/graphql/schema"
 )
 
-func IntValues(ctx *cli.Context, condition schema.BatchMetricConditions, duration schema.Duration) schema.IntValues {
-	var response map[string]schema.IntValues
+func IntValues(ctx *cli.Context, condition schema.MetricsCondition, duration schema.Duration) int {
+	var response map[string]int
 
-	request := graphql.NewRequest(assets.Read("graphqls/metrics/IntValues.graphql"))
+	request := graphql.NewRequest(assets.Read("graphqls/metrics/MetricsValue.graphql"))
 
-	request.Var("metric", condition)
+	request.Var("condition", condition)
 	request.Var("duration", duration)
 
 	client.ExecuteQueryOrFail(ctx, request, &response)
@@ -80,3 +78,15 @@
 
 	return response["result"]
 }
+
+func SortMetrics(ctx *cli.Context, condition schema.TopNCondition, duration schema.Duration) []*schema.SelectedRecord {
+	var response map[string][]*schema.SelectedRecord
+
+	request := graphql.NewRequest(assets.Read("graphqls/metrics/SortMetrics.graphql"))
+	request.Var("condition", condition)
+	request.Var("duration", duration)
+
+	client.ExecuteQueryOrFail(ctx, request, &response)
+
+	return response["result"]
+}