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  }