func (s *PowerFlexService) GetSDCStatistics(ctx context.Context, nodes []corev1.Node, sdcs []StatisticsGetter) {
	start := time.Now()
	defer s.timeSince(start, "GetSDCStatistics")
	if s.MetricsWrapper == nil {
		s.Logger.Warn("no MetricsWrapper provided for getting SDCStatistics")
		return
	}
	if s.MaxPowerFlexConnections == 0 {
		s.Logger.Debug("using DefaultMaxPowerFlexConnections")
		s.MaxPowerFlexConnections = DefaultMaxPowerFlexConnections
	}
	for range s.pushSDCMetrics(ctx, s.gatherSDCMetrics(ctx, nodes, s.sdcServer(sdcs))) {
	}
}
GetSDCStatistics records I/O statistics for the given list of SDCs
package service
import (
	"context"
	"fmt"
	"sync"
	"time"
	"github.com/dell/karavi-metrics-powerflex/internal/k8s"
	"github.com/sirupsen/logrus"
	sio "github.com/dell/goscaleio"
	types "github.com/dell/goscaleio/types/v1"
	corev1 "k8s.io/api/core/v1"
	v1 "k8s.io/api/storage/v1"
)
var _ Service = (*PowerFlexService)(nil)
const (
	DefaultMaxPowerFlexConnections = 10
)
type Service interface {
	GetSDCs(context.Context, PowerFlexClient, SDCFinder) ([]StatisticsGetter, error)
	GetSDCStatistics(context.Context, []corev1.Node, []StatisticsGetter)
	GetVolumes(context.Context, []StatisticsGetter) ([]VolumeStatisticsGetter, error)
	ExportVolumeStatistics(context.Context, []VolumeStatisticsGetter, VolumeFinder)
	GetStorageClasses(ctx context.Context, client PowerFlexClient, storageClassFinder StorageClassFinder) ([]StorageClassMeta, error)
	GetStoragePoolStatistics(ctx context.Context, storageClassMetas []StorageClassMeta)
}
type StatisticsGetter interface {
	GetStatistics() (*types.SdcStatistics, error)
	GetVolume() ([]*types.Volume, error)
	FindVolumes() ([]*sio.Volume, error)
}
type VolumeStatisticsGetter interface {
	GetVolumeStatistics() (*types.VolumeStatistics, error)
}
type PowerFlexClient interface {
	Authenticate(*sio.ConfigConnect) (sio.Cluster, error)
	GetInstance(string) ([]*types.System, error)
	FindSystem(string, string, string) (*sio.System, error)
	GetStoragePool(href string) ([]*types.StoragePool, error)
}
type PowerFlexSystem interface {
	FindSdc(string, string) (*sio.Sdc, error)
}
type PowerFlexService struct {
	MetricsWrapper          MetricsRecorder
	MaxPowerFlexConnections int
	Logger                  *logrus.Logger
}
type SDCFinder interface {
	GetSDCGuids() ([]string, error)
}
type StorageClassFinder interface {
	GetStorageClasses() ([]v1.StorageClass, error)
}
type VolumeFinder interface {
	GetPersistentVolumes() ([]k8s.VolumeInfo, error)
}
type NodeFinder interface {
	GetNodes() ([]corev1.Node, error)
}
type StoragePoolStatisticsGetter interface {
	GetStatistics() (*types.Statistics, error)
}
type LeaderElector interface {
	InitLeaderElection(string, string) error
	IsLeader() bool
}
func (s *PowerFlexService) GetSDCs(ctx context.Context, client PowerFlexClient, sdcFinder SDCFinder) ([]StatisticsGetter, error) {
	var sdcs []StatisticsGetter
	sdcGUIDs, err := sdcFinder.GetSDCGuids()
	if err != nil {
		return nil, err
	}
	s.Logger.WithField("sdc_guids", sdcGUIDs).Debug("get sdc guids")
	if len(sdcGUIDs) == 0 {
		return sdcs, nil
	}
	systems, err := client.GetInstance("")
	if err != nil {
		return nil, err
	}
	for _, system := range systems {
		s.Logger.WithFields(logrus.Fields{"system_id": system.ID, "system_name": system.Name}).Debug("looking up system")
		sys, err := SystemFinder(client, system.ID, system.Name, "")
		if err != nil {
			return nil, err
		}
		s.Logger.WithFields(logrus.Fields{"system": sys}).Debug("found system")
		for _, sdcGUID := range sdcGUIDs {
			sdc, err := sys.FindSdc("SdcGuid", sdcGUID)
			if err != nil {
				s.Logger.WithField("sdc_guid", sdcGUID).Warn("unable to find SDC with GUID")
			} else {
				s.Logger.WithFields(logrus.Fields{"sdc_guid": sdcGUID}).Debug("found sdc")
				sdcs = append(sdcs, sdc)
			}
		}
	}
	return sdcs, nil
}
var SystemFinder = func(client PowerFlexClient, id string, name string, href string) (PowerFlexSystem, error) {
	return client.FindSystem(id, name, href)
}
func GetSDCMeta(sdc interface{}, nodes []corev1.Node) *SDCMeta {
	switch v := sdc.(type) {
	case *sio.Sdc:
		var name string
	loop:
		for _, node := range nodes {
			for _, addr := range node.Status.Addresses {
				if addr.Address == v.Sdc.SdcIp {
					name = node.GetName()
					break loop
				}
			}
		}
		return &SDCMeta{
			Name:    name,
			ID:      v.Sdc.ID,
			IP:      v.Sdc.SdcIp,
			SdcGUID: v.Sdc.SdcGuid,
		}
	default:
		return &SDCMeta{}
	}
}
type SDCMetricsRecord struct {
	sdcMeta *SDCMeta
	readBW, writeBW,
	readIOPS, writeIOPS,
	readLatency, writeLatency float64
}
type VolumeMetricsRecord struct {
	volumeMeta *VolumeMeta
	readBW, writeBW,
	readIOPS, writeIOPS,
	readLatency, writeLatency float64
}