This is an automated email from the ASF dual-hosted git repository. hoshea pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/skywalking-cli.git
The following commit(s) were added to refs/heads/master by this push: new 2f77929 Refactor `metrics` to adopt metrics-v2 protocol (#70) 2f77929 is described below commit 2f779298ff7caaa87e1883d4bfec36e599e35d75 Author: Hoshea Jiang <fgk...@gmail.com> AuthorDate: Sun Oct 25 12:31:18 2020 +0800 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 --- README.md | 49 +++++----- .../graphqls/aggregation/AllEndpointTopN.graphql | 27 ------ .../aggregation/AllServiceInstanceTopN.graphql | 27 ------ assets/graphqls/aggregation/EndpointTopN.graphql | 28 ------ .../aggregation/ServiceInstanceTopN.graphql | 28 ------ assets/graphqls/aggregation/ServiceTopN.graphql | 27 ------ assets/graphqls/metrics/IntValues.graphql | 22 ----- ...inearIntValues.graphql => MetricsValue.graphql} | 6 +- .../{dashboard => metrics}/SortMetrics.graphql | 0 commands/flags/metrics.go | 37 ++++++++ commands/interceptor/scope.go | 45 ++++++++++ commands/interceptor/scope_test.go | 80 +++++++++++++++++ commands/metrics/aggregation/topn.go | 57 ++++-------- commands/metrics/linear/linear-metrics.go | 37 ++++---- commands/metrics/linear/multiple-linear-metrics.go | 18 ++-- commands/metrics/single/single-metrics.go | 57 ++++++------ commands/metrics/thermodynamic/thermodynamic.go | 22 ++--- graphql/aggregation/aggregation.go | 100 --------------------- graphql/dashboard/global.go | 10 +-- graphql/metrics/metrics.go | 28 ++++-- 20 files changed, 292 insertions(+), 413 deletions(-) diff --git a/README.md b/README.md index 4f1623a..62df566 100644 --- a/README.md +++ b/README.md @@ -160,12 +160,12 @@ Ascii Graph, like coloring in terminal, so please use `json` or `yaml` instead. <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 @@ Ascii Graph, like coloring in terminal, so please use `json` or `yaml` instead. <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 @@ Ascii Graph, like coloring in terminal, so please use `json` or `yaml` instead. <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 @@ Ascii Graph, like coloring in terminal, so please use `json` or `yaml` instead. <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 @@ Ascii Graph, like coloring in terminal, so please use `json` or `yaml` instead. <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 @@ otherwise, <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 @@ $ ./bin/swctl --display=graph --debug metrics multiple-linear --name all_percent <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 - 6e0e2e1cc63145859a21fc7bf7f [...] ``` </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 @@ $ ./bin/swctl metrics top 5 --name endpoint_sla --service-id 3 <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,4 [...] ``` ```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/IntValues.graphql b/assets/graphqls/metrics/IntValues.graphql deleted file mode 100644 index 1138172..0000000 --- a/assets/graphqls/metrics/IntValues.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: BatchMetricConditions!, $duration: Duration!) { - result: getValues(metric: $metric, duration: $duration) { - values { id value } - } -} diff --git a/assets/graphqls/metrics/LinearIntValues.graphql b/assets/graphqls/metrics/MetricsValue.graphql similarity index 83% rename from assets/graphqls/metrics/LinearIntValues.graphql rename to assets/graphqls/metrics/MetricsValue.graphql index 6249db2..9458b04 100644 --- a/assets/graphqls/metrics/LinearIntValues.graphql +++ b/assets/graphqls/metrics/MetricsValue.graphql @@ -15,8 +15,6 @@ # specific language governing permissions and limitations # under the License. -query ($metric: MetricCondition!, $duration: Duration!) { - result: getLinearIntValues(metric: $metric, duration: $duration) { - values { 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 @@ package aggregation 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 @@ var TopN = cli.Command{ 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 @@ var TopN = cli.Command{ 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 @@ var TopN = cli.Command{ 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 @@ var TopN = cli.Command{ 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 @@ var Single = cli.Command{ 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 @@ var Single = cli.Command{ 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 @@ var Single = cli.Command{ 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 @@ var Multiple = cli.Command{ 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 @@ var Multiple = cli.Command{ 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 @@ var Multiple = cli.Command{ 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 @@ var Command = cli.Command{ 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 @@ var Command = cli.Command{ end := ctx.String("end") start := ctx.String("start") step := ctx.Generic("step") - metricsName := ctx.String("name") - idsString := ctx.StringSlice("ids") - var ids []string + metricsName := ctx.String("name") + serviceName := ctx.String("service") + normal := true + scope := interceptor.ParseScope(metricsName) - 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, - }) + } + + 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: metricsValues.Values}) + 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 @@ var Command = cli.Command{ 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 @@ var Command = cli.Command{ 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 @@ import ( "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 @@ func Metrics(ctx *cli.Context, duration schema.Duration) [][]*schema.SelectedRec } 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/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" + + "github.com/machinebox/graphql" + "github.com/urfave/cli" ) -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 @@ func Thermodynamic(ctx *cli.Context, condition schema.MetricsCondition, duration 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"] +}