istio.io/istio@v0.0.0-20240520182934-d79c90f27776/tests/integration/telemetry/api/istioctl_metrics_test.go (about) 1 //go:build integ 2 // +build integ 3 4 // Copyright Istio Authors 5 // 6 // Licensed under the Apache License, Version 2.0 (the "License"); 7 // you may not use this file except in compliance with the License. 8 // You may obtain a copy of the License at 9 // 10 // http://www.apache.org/licenses/LICENSE-2.0 11 // 12 // Unless required by applicable law or agreed to in writing, software 13 // distributed under the License is distributed on an "AS IS" BASIS, 14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 // See the License for the specific language governing permissions and 16 // limitations under the License. 17 18 package api 19 20 import ( 21 "errors" 22 "strconv" 23 "strings" 24 "testing" 25 26 "istio.io/istio/pkg/test/framework" 27 "istio.io/istio/pkg/test/framework/components/istioctl" 28 "istio.io/istio/pkg/test/util/retry" 29 ) 30 31 // TestIstioctlMetrics contains a basic validation of the experimental 32 // metrics command. It validates that values are being returned when there is 33 // traffic and that the expected default output format is matched. 34 func TestIstioctlMetrics(t *testing.T) { 35 framework.NewTest(t). 36 Run(func(t framework.TestContext) { 37 retry.UntilSuccessOrFail(t, func() error { 38 if err := SendTraffic(GetClientInstances()[0]); err != nil { 39 return err 40 } 41 return validateDefaultOutput(t, GetTarget().Config().Service) 42 }, retry.Delay(framework.TelemetryRetryDelay), retry.Timeout(framework.TelemetryRetryTimeout)) 43 }) 44 } 45 46 func validateDefaultOutput(t framework.TestContext, workload string) error { // nolint:interfacer 47 t.Helper() 48 istioCtl := istioctl.NewOrFail(t, t, istioctl.Config{}) 49 args := []string{"experimental", "metrics", workload} 50 output, stderr, fErr := istioCtl.Invoke(args) 51 if fErr != nil { 52 t.Logf("Unwanted exception for 'istioctl %s': %v. Stderr: %v", strings.Join(args, " "), fErr, stderr) 53 return fErr 54 } 55 56 // output will be something like 57 // WORKLOAD TOTAL RPS ERROR RPS P50 LATENCY P90 LATENCY P99 LATENCY 58 // server 0.182 0.000 40ms 74ms 97ms 59 // 60 lines := strings.Split(output, "\n") 61 if len(lines) != 3 { 62 t.Logf("Expected 2 lines of output, got %q", output) 63 return errors.New("unexpected output (incorrect number of lines)") 64 } 65 fields := strings.Fields(lines[1]) 66 if len(fields) != 6 { 67 t.Logf("Expected 6 columns, got %#v", fields) 68 return errors.New("unexpected output (incorrect number of columns)") 69 } 70 if fields[0] != workload { 71 t.Logf("Expected column 1 to be %q, got %#v", workload, fields) 72 return errors.New("unexpected output (incorrect workload)") 73 } 74 totalRPS, fErr := strconv.ParseFloat(fields[1], 32) 75 if fErr != nil { 76 t.Logf("Expected column 2 to show totalRPS, got %#v", fields) 77 return fErr 78 } 79 if totalRPS <= 0.001 { 80 t.Logf("Expected column 2 to show totalRPS more than 0.001, got %#v", fields) 81 return errors.New("unexpected output (incorrect RPS)") 82 } 83 return nil 84 }