k8s.io/perf-tests/clusterloader2@v0.0.0-20240304094227-64bdb12da87e/pkg/measurement/common/prometheus_measurement.go (about)

     1  /*
     2  Copyright 2019 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package common
    18  
    19  import (
    20  	"fmt"
    21  	"time"
    22  
    23  	"github.com/prometheus/common/model"
    24  	"k8s.io/klog/v2"
    25  	"k8s.io/perf-tests/clusterloader2/pkg/errors"
    26  	"k8s.io/perf-tests/clusterloader2/pkg/measurement"
    27  	measurementutil "k8s.io/perf-tests/clusterloader2/pkg/measurement/util"
    28  	prom "k8s.io/perf-tests/clusterloader2/pkg/prometheus/clients"
    29  	"k8s.io/perf-tests/clusterloader2/pkg/util"
    30  )
    31  
    32  func CreatePrometheusMeasurement(gatherer Gatherer) measurement.Measurement {
    33  	return &prometheusMeasurement{
    34  		gatherer: gatherer,
    35  	}
    36  }
    37  
    38  // QueryExecutor is an interface for queryning Prometheus server.
    39  type QueryExecutor interface {
    40  	Query(query string, queryTime time.Time) ([]*model.Sample, error)
    41  }
    42  
    43  // Gatherer is an interface for measurements based on Prometheus metrics. Those measurments don't require any preparation.
    44  // It's assumed Prometheus is up, running and instructed to scrape required metrics in the test cluster
    45  // (please see clusterloader2/pkg/prometheus/manifests).
    46  type Gatherer interface {
    47  	Configure(config *measurement.Config) error
    48  	Gather(executor QueryExecutor, startTime, endTime time.Time, config *measurement.Config) ([]measurement.Summary, error)
    49  	IsEnabled(config *measurement.Config) bool
    50  	String() string
    51  }
    52  
    53  type prometheusMeasurement struct {
    54  	gatherer Gatherer
    55  
    56  	startTime time.Time
    57  }
    58  
    59  func (m *prometheusMeasurement) Execute(config *measurement.Config) ([]measurement.Summary, error) {
    60  	prometheusClient, err := util.GetStringOrDefault(config.Params, "prometheusClient", "inCluster")
    61  	if err != nil {
    62  		return nil, err
    63  	}
    64  	if prometheusClient != "inCluster" && prometheusClient != "managed" {
    65  		return nil, fmt.Errorf("unknown Prometheus client")
    66  	}
    67  	if prometheusClient == "inCluster" && config.PrometheusFramework == nil {
    68  		klog.Warningf("%s: Prometheus is disabled, skipping the measurement!", config.Identifier)
    69  		return nil, nil
    70  	}
    71  
    72  	if !m.gatherer.IsEnabled(config) {
    73  		klog.Warningf("%s: disabled, skipping the measuerment!", config.Identifier)
    74  		return nil, nil
    75  	}
    76  
    77  	action, err := util.GetString(config.Params, "action")
    78  	if err != nil {
    79  		return nil, err
    80  	}
    81  
    82  	switch action {
    83  	case "start":
    84  		if err := m.gatherer.Configure(config); err != nil {
    85  			return nil, err
    86  		}
    87  		klog.V(2).Infof("%s has started", config.Identifier)
    88  		m.startTime = time.Now()
    89  		return nil, nil
    90  	case "gather":
    91  		klog.V(2).Infof("%s gathering results", config.Identifier)
    92  		enableViolations, err := util.GetBoolOrDefault(config.Params, "enableViolations", false)
    93  		if err != nil {
    94  			return nil, err
    95  		}
    96  
    97  		var pc prom.Client
    98  		switch prometheusClient {
    99  		case "inCluster":
   100  			pc = prom.NewInClusterPrometheusClient(config.PrometheusFramework.GetClientSets().GetClient())
   101  		case "managed":
   102  			pc, err = config.CloudProvider.GetManagedPrometheusClient()
   103  			if err != nil {
   104  				return nil, fmt.Errorf("error while creating managed Prometheus client: %w", err)
   105  			}
   106  		}
   107  		executor := measurementutil.NewQueryExecutor(pc)
   108  
   109  		summary, err := m.gatherer.Gather(executor, m.startTime, time.Now(), config)
   110  		if err != nil {
   111  			if !errors.IsMetricViolationError(err) {
   112  				klog.Errorf("%s gathering error: %v", config.Identifier, err)
   113  				return nil, err
   114  			}
   115  			if !enableViolations {
   116  				err = nil
   117  			}
   118  		}
   119  		return summary, err
   120  	default:
   121  		return nil, fmt.Errorf("unknown action: %v", action)
   122  	}
   123  }
   124  
   125  func (m *prometheusMeasurement) Dispose() {}
   126  
   127  func (m *prometheusMeasurement) String() string {
   128  	return m.gatherer.String()
   129  }