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

     1  /*
     2  Copyright 2018 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 measurement
    18  
    19  import (
    20  	"fmt"
    21  	"sync"
    22  
    23  	"k8s.io/perf-tests/clusterloader2/pkg/config"
    24  	"k8s.io/perf-tests/clusterloader2/pkg/framework"
    25  )
    26  
    27  // measurementManager manages all measurement executions.
    28  type measurementManager struct {
    29  	clusterFramework    *framework.Framework
    30  	clusterLoaderConfig *config.ClusterLoaderConfig
    31  	prometheusFramework *framework.Framework
    32  	templateProvider    *config.TemplateProvider
    33  
    34  	lock sync.Mutex
    35  	// map from method type and identifier to measurement instance.
    36  	measurements map[string]map[string]Measurement
    37  	summaries    []Summary
    38  }
    39  
    40  // Manager provides the interface for measurementManager
    41  type Manager interface {
    42  	Execute(methodName string, identifier string, params map[string]interface{}) error
    43  	GetSummaries() []Summary
    44  	Dispose()
    45  }
    46  
    47  // CreateManager creates new instance of measurementManager.
    48  func CreateManager(clusterFramework, prometheusFramework *framework.Framework, templateProvider *config.TemplateProvider, config *config.ClusterLoaderConfig) Manager {
    49  	return &measurementManager{
    50  		clusterFramework:    clusterFramework,
    51  		clusterLoaderConfig: config,
    52  		prometheusFramework: prometheusFramework,
    53  		templateProvider:    templateProvider,
    54  		measurements:        make(map[string]map[string]Measurement),
    55  		summaries:           make([]Summary, 0),
    56  	}
    57  }
    58  
    59  // Execute executes measurement based on provided identifier, methodName and params.
    60  func (mm *measurementManager) Execute(methodName string, identifier string, params map[string]interface{}) error {
    61  	measurementInstance, err := mm.getMeasurementInstance(methodName, identifier)
    62  	if err != nil {
    63  		return err
    64  	}
    65  	config := &Config{
    66  		ClusterFramework:    mm.clusterFramework,
    67  		PrometheusFramework: mm.prometheusFramework,
    68  		Params:              params,
    69  		TemplateProvider:    mm.templateProvider,
    70  		Identifier:          identifier,
    71  		CloudProvider:       mm.clusterLoaderConfig.ClusterConfig.Provider,
    72  		ClusterLoaderConfig: mm.clusterLoaderConfig,
    73  	}
    74  
    75  	clusterVersion, err := mm.clusterFramework.GetDiscoveryClient().ServerVersion()
    76  	if err != nil {
    77  		return fmt.Errorf("failed to get cluster version")
    78  	}
    79  	config.ClusterVersion = *clusterVersion
    80  
    81  	summaries, err := measurementInstance.Execute(config)
    82  	mm.summaries = append(mm.summaries, summaries...)
    83  	return err
    84  }
    85  
    86  // GetSummaries returns collected summaries.
    87  func (mm *measurementManager) GetSummaries() []Summary {
    88  	return mm.summaries
    89  }
    90  
    91  // Dispose disposes measurement instances.
    92  func (mm *measurementManager) Dispose() {
    93  	for _, instances := range mm.measurements {
    94  		for _, measurement := range instances {
    95  			measurement.Dispose()
    96  		}
    97  	}
    98  }
    99  
   100  func (mm *measurementManager) getMeasurementInstance(methodName string, identifier string) (Measurement, error) {
   101  	mm.lock.Lock()
   102  	defer mm.lock.Unlock()
   103  	if _, exists := mm.measurements[methodName]; !exists {
   104  		mm.measurements[methodName] = make(map[string]Measurement)
   105  	}
   106  	if _, exists := mm.measurements[methodName][identifier]; !exists {
   107  		measurementInstance, err := factory.createMeasurement(methodName)
   108  		if err != nil {
   109  			return nil, err
   110  		}
   111  		mm.measurements[methodName][identifier] = measurementInstance
   112  	}
   113  	return mm.measurements[methodName][identifier], nil
   114  }