From f0b0b2715e271760235a8faa24a69063c55a32d3 Mon Sep 17 00:00:00 2001 From: Mrproliu <741550557@qq.com> Date: Wed, 29 Mar 2023 11:07:07 +0800 Subject: [PATCH] Add `isEmptyValue` field in metrics related commands --- .github/workflows/command-tests.yml | 2 +- .github/workflows/golangci-lint.yml | 2 +- CHANGES.md | 1 + Makefile | 2 +- .../metrics/LabeledMetricsValues.graphql | 1 + assets/graphqls/metrics/MetricsValues.graphql | 1 + .../metrics/NullableMetricsValue.graphql | 1 + .../metrics/single/nullable-metrics.go | 2 +- pkg/display/displayable/MetricValue.go | 23 +++++++++++++++++++ pkg/display/graph/graph.go | 2 +- pkg/display/graph/linear/linear.go | 12 ++++++---- pkg/graphql/dashboard/global.go | 12 ++++++---- pkg/graphql/utils/adapter.go | 16 +++++++++---- pkg/graphql/utils/adapter_test.go | 22 ++++++++++-------- .../basic/expected/dependency-instance.yml | 8 +++---- test/cases/basic/expected/layer-list.yml | 16 ++++++++----- .../basic/expected/metrics-has-value.yml | 4 +++- 17 files changed, 85 insertions(+), 42 deletions(-) create mode 100644 pkg/display/displayable/MetricValue.go diff --git a/.github/workflows/command-tests.yml b/.github/workflows/command-tests.yml index 2fb5e36d..26c9c267 100644 --- a/.github/workflows/command-tests.yml +++ b/.github/workflows/command-tests.yml @@ -31,7 +31,7 @@ jobs: strategy: matrix: oap: - - e5950cc06279a83c64089f94613b06ec0ef0d911 + - 6fa89c79917cb10dbf48591c46abee3b513a2bab steps: - uses: actions/checkout@v2 - name: Check for go file changes diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 6d6da8f2..ab1450ac 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -47,5 +47,5 @@ jobs: if: steps.changes.outputs.src == 'true' uses: golangci/golangci-lint-action@v3 with: - version: latest + version: v1.50.0 args: --timeout 5m diff --git a/CHANGES.md b/CHANGES.md index 2d6cf7dc..76fce945 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -39,6 +39,7 @@ Release Notes. * Add components in topology related sub-commands. @mrproliu in https://github.com/apache/skywalking-cli/pull/175 * Add the sub-command `metrics nullable` for query the nullable metrics value. @mrproliu in https://github.com/apache/skywalking-cli/pull/176 * Adapt the sub-command `profiling trace` for adapt the new trace profiling protocol. @mrproliu in https://github.com/apache/skywalking-cli/pull/177 +* Add `isEmptyValue` field in metrics related sub-commands. @mrproliu in https://github.com/apache/skywalking-cli/pull/180 0.10.0 ------------------ diff --git a/Makefile b/Makefile index 2523a8d3..bd3b9b6c 100644 --- a/Makefile +++ b/Makefile @@ -58,7 +58,7 @@ deps: @$(GO_GET) -v -t -d ./... $(GO_LINT): - @$(GO_LINT) version > /dev/null 2>&1 || go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest + @$(GO_LINT) version > /dev/null 2>&1 || curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GO_PATH)/bin v1.50.0 $(LICENSE_EYE): @$(LICENSE_EYE) --version > /dev/null 2>&1 || go install github.com/apache/skywalking-eyes/cmd/license-eye@d38fe05 diff --git a/assets/graphqls/metrics/LabeledMetricsValues.graphql b/assets/graphqls/metrics/LabeledMetricsValues.graphql index 25fa78e6..1183db32 100644 --- a/assets/graphqls/metrics/LabeledMetricsValues.graphql +++ b/assets/graphqls/metrics/LabeledMetricsValues.graphql @@ -21,6 +21,7 @@ query ($condition: MetricsCondition!, $labels: [String!]!, $duration: Duration!) values { values { value + isEmptyValue } } } diff --git a/assets/graphqls/metrics/MetricsValues.graphql b/assets/graphqls/metrics/MetricsValues.graphql index 3d1c8a15..9433bc60 100644 --- a/assets/graphqls/metrics/MetricsValues.graphql +++ b/assets/graphqls/metrics/MetricsValues.graphql @@ -21,6 +21,7 @@ query ($condition: MetricsCondition!, $duration: Duration!) { values { values { value + isEmptyValue } } } diff --git a/assets/graphqls/metrics/NullableMetricsValue.graphql b/assets/graphqls/metrics/NullableMetricsValue.graphql index c460d3f4..fd7f3352 100644 --- a/assets/graphqls/metrics/NullableMetricsValue.graphql +++ b/assets/graphqls/metrics/NullableMetricsValue.graphql @@ -18,5 +18,6 @@ query ($condition: MetricsCondition!, $duration: Duration!) { result: readNullableMetricsValue(condition: $condition, duration: $duration) { value + isEmptyValue } } diff --git a/internal/commands/metrics/single/nullable-metrics.go b/internal/commands/metrics/single/nullable-metrics.go index 9b73abae..58ebd3cd 100644 --- a/internal/commands/metrics/single/nullable-metrics.go +++ b/internal/commands/metrics/single/nullable-metrics.go @@ -80,6 +80,6 @@ $ swctl metrics nullable --name endpoint_cpm --service-name business-zone::proje return err } - return display.Display(ctx, &displayable.Displayable{Data: metricsValue.Value}) + return display.Display(ctx, &displayable.Displayable{Data: metricsValue}) }, } diff --git a/pkg/display/displayable/MetricValue.go b/pkg/display/displayable/MetricValue.go new file mode 100644 index 00000000..502374cc --- /dev/null +++ b/pkg/display/displayable/MetricValue.go @@ -0,0 +1,23 @@ +// 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 displayable + +type MetricValue struct { + Value float64 + IsEmptyValue bool +} diff --git a/pkg/display/graph/graph.go b/pkg/display/graph/graph.go index d33ab528..64c850c6 100644 --- a/pkg/display/graph/graph.go +++ b/pkg/display/graph/graph.go @@ -38,7 +38,7 @@ import ( type ( Thermodynamic = api.HeatMap - LinearMetrics = map[string]float64 + LinearMetrics = map[string]*d.MetricValue MultiLinearMetrics = map[string]LinearMetrics Trace = api.Trace TraceBrief = api.TraceBrief diff --git a/pkg/display/graph/linear/linear.go b/pkg/display/graph/linear/linear.go index 0186b4db..ce4a29d1 100644 --- a/pkg/display/graph/linear/linear.go +++ b/pkg/display/graph/linear/linear.go @@ -24,6 +24,8 @@ import ( "sort" "strings" + "github.com/apache/skywalking-cli/pkg/display/displayable" + "github.com/mum4k/termdash" "github.com/mum4k/termdash/container" "github.com/mum4k/termdash/container/grid" @@ -39,7 +41,7 @@ const RootID = "root" const defaultSeriesLabel = "linear" -func NewLineChart(inputs map[string]float64) (lineChart *linechart.LineChart, err error) { +func NewLineChart(inputs map[string]*displayable.MetricValue) (lineChart *linechart.LineChart, err error) { if lineChart, err = linechart.New(linechart.YAxisAdaptive()); err != nil { return } @@ -49,13 +51,13 @@ func NewLineChart(inputs map[string]float64) (lineChart *linechart.LineChart, er return lineChart, err } -func SetLineChartSeries(lc *linechart.LineChart, inputs map[string]float64) error { +func SetLineChartSeries(lc *linechart.LineChart, inputs map[string]*displayable.MetricValue) error { xLabels, yValues := processInputs(inputs) return lc.Series(defaultSeriesLabel, yValues, linechart.SeriesXLabels(xLabels)) } // processInputs converts inputs into xLabels and yValues for line charts. -func processInputs(inputs map[string]float64) (xLabels map[int]string, yValues []float64) { +func processInputs(inputs map[string]*displayable.MetricValue) (xLabels map[int]string, yValues []float64) { index := 0 xLabels = map[int]string{} @@ -70,7 +72,7 @@ func processInputs(inputs map[string]float64) (xLabels map[int]string, yValues [ for _, name := range names { xLabels[index] = name - yValues[index] = inputs[name] + yValues[index] = inputs[name].Value index++ } return @@ -131,7 +133,7 @@ func layout(rows [][]grid.Element) ([]container.Option, error) { return builder.Build() } -func Display(cliCtx *cli.Context, inputs map[string]map[string]float64) error { +func Display(cliCtx *cli.Context, inputs map[string]map[string]*displayable.MetricValue) error { t, err := termbox.New() if err != nil { return err diff --git a/pkg/graphql/dashboard/global.go b/pkg/graphql/dashboard/global.go index cb3327f3..5b5adc58 100644 --- a/pkg/graphql/dashboard/global.go +++ b/pkg/graphql/dashboard/global.go @@ -23,6 +23,8 @@ import ( "strings" "sync" + "github.com/apache/skywalking-cli/pkg/display/displayable" + "golang.org/x/text/cases" "golang.org/x/text/language" api "skywalking.apache.org/repo/goapi/query" @@ -67,9 +69,9 @@ type GlobalTemplate struct { } type GlobalData struct { - Metrics [][]*api.SelectedRecord `json:"metrics"` - ResponseLatency map[string]map[string]float64 `json:"responseLatency"` - HeatMap api.HeatMap `json:"heatMap"` + Metrics [][]*api.SelectedRecord `json:"metrics"` + ResponseLatency map[string]map[string]*displayable.MetricValue `json:"responseLatency"` + HeatMap api.HeatMap `json:"heatMap"` } // Use singleton pattern to make sure to load template only once. @@ -166,7 +168,7 @@ func Metrics(ctx *cli.Context, duration api.Duration) ([][]*api.SelectedRecord, return ret, nil } -func responseLatency(ctx *cli.Context, duration api.Duration) map[string]map[string]float64 { +func responseLatency(ctx *cli.Context, duration api.Duration) map[string]map[string]*displayable.MetricValue { template, err := LoadTemplate(ctx.String("template")) if err != nil { return nil @@ -232,7 +234,7 @@ func Global(ctx *cli.Context, duration api.Duration) (*GlobalData, error) { } wg.Done() }() - var rl map[string]map[string]float64 + var rl map[string]map[string]*displayable.MetricValue go func() { rl = responseLatency(ctx, duration) wg.Done() diff --git a/pkg/graphql/utils/adapter.go b/pkg/graphql/utils/adapter.go index f8af4627..de40351c 100644 --- a/pkg/graphql/utils/adapter.go +++ b/pkg/graphql/utils/adapter.go @@ -20,14 +20,17 @@ package utils import ( "time" + "github.com/apache/skywalking-cli/pkg/display/displayable" + api "skywalking.apache.org/repo/goapi/query" "github.com/apache/skywalking-cli/internal/logger" ) // MetricsValuesArrayToMap converts Array of MetricsValues into a map that uses time as key. -func MetricsValuesArrayToMap(duration api.Duration, mvArray []api.MetricsValues, labelsMap map[string]string) map[string]map[string]float64 { - ret := make(map[string]map[string]float64, len(mvArray)) +func MetricsValuesArrayToMap(duration api.Duration, mvArray []api.MetricsValues, + labelsMap map[string]string) map[string]map[string]*displayable.MetricValue { + ret := make(map[string]map[string]*displayable.MetricValue, len(mvArray)) for _, mvs := range mvArray { label := *mvs.Label if l, ok := labelsMap[label]; ok { @@ -39,9 +42,9 @@ func MetricsValuesArrayToMap(duration api.Duration, mvArray []api.MetricsValues, } // MetricsValuesToMap converts MetricsValues into a map that uses time as key. -func MetricsValuesToMap(duration api.Duration, metricsValues api.MetricsValues) map[string]float64 { +func MetricsValuesToMap(duration api.Duration, metricsValues api.MetricsValues) map[string]*displayable.MetricValue { kvInts := metricsValues.Values.Values - ret := map[string]float64{} + ret := map[string]*displayable.MetricValue{} format := StepFormats[duration.Step] startTime, err := time.Parse(format, duration.Start) @@ -51,7 +54,10 @@ func MetricsValuesToMap(duration api.Duration, metricsValues api.MetricsValues) step := StepDuration[duration.Step] for idx, value := range kvInts { - ret[startTime.Add(time.Duration(idx)*step).Format(format)] = float64(value.Value) + ret[startTime.Add(time.Duration(idx)*step).Format(format)] = &displayable.MetricValue{ + Value: float64(value.Value), + IsEmptyValue: value.IsEmptyValue, + } } return ret diff --git a/pkg/graphql/utils/adapter_test.go b/pkg/graphql/utils/adapter_test.go index f13c42cc..23e6db19 100644 --- a/pkg/graphql/utils/adapter_test.go +++ b/pkg/graphql/utils/adapter_test.go @@ -21,6 +21,8 @@ import ( "reflect" "testing" + "github.com/apache/skywalking-cli/pkg/display/displayable" + api "skywalking.apache.org/repo/goapi/query" ) @@ -32,7 +34,7 @@ func TestMetricsToMap(t *testing.T) { tests := []struct { name string args args - want map[string]float64 + want map[string]*displayable.MetricValue }{ { name: "Should convert to map", @@ -57,15 +59,15 @@ func TestMetricsToMap(t *testing.T) { }, }, }, - want: map[string]float64{ - "2020-01-01 0000": 0, - "2020-01-01 0001": 1, - "2020-01-01 0002": 2, - "2020-01-01 0003": 3, - "2020-01-01 0004": 4, - "2020-01-01 0005": 5, - "2020-01-01 0006": 6, - "2020-01-01 0007": 7, + want: map[string]*displayable.MetricValue{ + "2020-01-01 0000": {Value: 0, IsEmptyValue: false}, + "2020-01-01 0001": {Value: 1, IsEmptyValue: false}, + "2020-01-01 0002": {Value: 2, IsEmptyValue: false}, + "2020-01-01 0003": {Value: 3, IsEmptyValue: false}, + "2020-01-01 0004": {Value: 4, IsEmptyValue: false}, + "2020-01-01 0005": {Value: 5, IsEmptyValue: false}, + "2020-01-01 0006": {Value: 6, IsEmptyValue: false}, + "2020-01-01 0007": {Value: 7, IsEmptyValue: false}, }, }, } diff --git a/test/cases/basic/expected/dependency-instance.yml b/test/cases/basic/expected/dependency-instance.yml index 806149e2..bfa7f057 100644 --- a/test/cases/basic/expected/dependency-instance.yml +++ b/test/cases/basic/expected/dependency-instance.yml @@ -17,7 +17,7 @@ nodes: {{- contains .nodes }} - id: {{ b64enc "provider" }}.1_{{ b64enc "provider1" }} name: provider1 - type: Python + type: "" isreal: true serviceid: {{ b64enc "provider" }}.1 servicename: provider @@ -31,11 +31,9 @@ nodes: calls: {{- contains .calls }} - source: {{ b64enc "consumer" }}.1_{{ b64enc "consumer1" }} - sourcecomponents: - - Python + sourcecomponents: [] target: {{ b64enc "provider" }}.1_{{ b64enc "provider1" }} - targetcomponents: - - Python + targetcomponents: [] id: {{ b64enc "consumer" }}.1_{{ b64enc "consumer1" }}-{{ b64enc "provider" }}.1_{{ b64enc "provider1" }} detectpoints: {{- contains .detectpoints }} diff --git a/test/cases/basic/expected/layer-list.yml b/test/cases/basic/expected/layer-list.yml index faa1146b..d400af20 100644 --- a/test/cases/basic/expected/layer-list.yml +++ b/test/cases/basic/expected/layer-list.yml @@ -14,23 +14,27 @@ # limitations under the License. - BROWSER +- MESH +- GENERAL +- FAAS +- MESH_CP +- SO11Y_SATELLITE +- K8S_SERVICE - VIRTUAL_GATEWAY +- AWS_EKS - MQ - MYSQL - VIRTUAL_DATABASE - K8S - VIRTUAL_MQ -- MESH -- GENERAL - CACHE -- FAAS -- MESH_CP +- OS_WINDOWS - MESH_DP - SO11Y_OAP - DATABASE - OS_LINUX -- SO11Y_SATELLITE -- K8S_SERVICE - APISIX - VIRTUAL_CACHE - POSTGRESQL +- AWS_S3 +- AWS_DYNAMODB \ No newline at end of file diff --git a/test/cases/basic/expected/metrics-has-value.yml b/test/cases/basic/expected/metrics-has-value.yml index 75b746f2..ba4c7602 100644 --- a/test/cases/basic/expected/metrics-has-value.yml +++ b/test/cases/basic/expected/metrics-has-value.yml @@ -15,5 +15,7 @@ {{- contains . }} - key: {{ notEmpty .key }} - value: {{ ge .value 1 }} + value: + value: {{ ge .value.value 1 }} + isemptyvalue: false {{- end }}