From c1fe5c33aa90ea6c8d6982fb4bbc0a8986345e59 Mon Sep 17 00:00:00 2001 From: Rahul Date: Wed, 11 Oct 2023 20:23:57 +0530 Subject: [PATCH] feat: add flexgroup to fabricpool panels (#2419) * feat: add flexgroup to fabricpool panels * feat: address review comments * feat: address review comments * feat: address review comments --- cmd/collectors/fabricpool.go | 150 ++++++++++++++++++ .../restperf/plugins/fabricpool/fabricpool.go | 22 ++- .../zapiperf/plugins/fabricpool/fabricpool.go | 38 +++++ cmd/collectors/zapiperf/zapiperf.go | 3 + .../9.12.0/wafl_comp_aggr_vol_bin.yaml | 3 +- .../cdot/9.8.0/wafl_comp_aggr_vol_bin.yaml | 4 + grafana/dashboards/cmode/volume.json | 8 +- 7 files changed, 222 insertions(+), 6 deletions(-) create mode 100644 cmd/collectors/fabricpool.go create mode 100644 cmd/collectors/zapiperf/plugins/fabricpool/fabricpool.go diff --git a/cmd/collectors/fabricpool.go b/cmd/collectors/fabricpool.go new file mode 100644 index 000000000..93b63cf49 --- /dev/null +++ b/cmd/collectors/fabricpool.go @@ -0,0 +1,150 @@ +package collectors + +import ( + "github.com/netapp/harvest/v2/pkg/logging" + "github.com/netapp/harvest/v2/pkg/matrix" + "golang.org/x/exp/maps" + "regexp" + "strings" +) + +var re = regexp.MustCompile(`^(.*)__(\d{4})$`) + +func GetFlexGroupFabricPoolMetrics(dataMap map[string]*matrix.Matrix, object string, opName string, includeConstituents bool, l *logging.Logger) (*matrix.Matrix, error) { + var ( + err error + latencyCacheMetrics []string + ) + + data := dataMap[object] + opsKeyPrefix := "temp_" + + cache := data.Clone(matrix.With{Data: false, Metrics: true, Instances: false, ExportInstances: true}) + cache.UUID += ".FabricPool" + + // collect latency_average metrics names + for mKey := range cache.GetMetrics() { + if strings.HasPrefix(mKey, "cloud_bin_op_latency_average") { + latencyCacheMetrics = append(latencyCacheMetrics, mKey) + } + } + + // create flexgroup instance cache + for _, i := range data.GetInstances() { + if !i.IsExportable() { + continue + } + if match := re.FindStringSubmatch(i.GetLabel("volume")); len(match) == 3 { + key := i.GetLabel("svm") + "." + match[1] + if cache.GetInstance(key) == nil { + fg, _ := cache.NewInstance(key) + fg.SetLabels(maps.Clone(i.GetLabels())) + fg.SetLabel("volume", match[1]) + } + i.SetExportable(includeConstituents) + } + } + + l.Logger.Debug().Int("size", len(cache.GetInstances())).Msg("extracted flexgroup volumes") + + // create summary + for _, i := range data.GetInstances() { + if match := re.FindStringSubmatch(i.GetLabel("volume")); len(match) == 3 { + // instance key is svm.flexgroup-volume + key := i.GetLabel("svm") + "." + match[1] + + fg := cache.GetInstance(key) + if fg == nil { + l.Logger.Error().Str("key", key).Msg("instance not in local cache") + continue + } + + for mkey, m := range data.GetMetrics() { + if !m.IsExportable() && m.GetType() != "float64" { + continue + } + + fgm := cache.GetMetric(mkey) + if fgm == nil { + l.Logger.Error().Str("key", mkey).Msg("metric not in local cache") + continue + } + + if value, ok := m.GetValueFloat64(i); ok { + fgv, _ := fgm.GetValueFloat64(fg) + + // non-latency metrics: simple sum + if !strings.HasPrefix(mkey, "cloud_bin_op_latency_average") { + err := fgm.SetValueFloat64(fg, fgv+value) + if err != nil { + l.Logger.Error().Err(err).Msg("error") + } + continue + } + + // latency metric: weighted sum + opsKey := strings.Replace(mkey, "cloud_bin_op_latency_average", opName, 1) + + if ops := data.GetMetric(opsKey); ops != nil { + if opsValue, ok := ops.GetValueFloat64(i); ok { + var tempOpsV float64 + + prod := value * opsValue + tempOpsKey := opsKeyPrefix + opsKey + tempOps := cache.GetMetric(tempOpsKey) + + if tempOps == nil { + if tempOps, err = cache.NewMetricFloat64(tempOpsKey); err != nil { + return nil, err + } + tempOps.SetExportable(false) + } else { + tempOpsV, _ = tempOps.GetValueFloat64(fg) + } + if value != 0 { + err = tempOps.SetValueFloat64(fg, tempOpsV+opsValue) + if err != nil { + l.Logger.Error().Err(err).Msg("error") + } + } + err = fgm.SetValueFloat64(fg, fgv+prod) + if err != nil { + l.Logger.Error().Err(err).Msg("error") + } + } else { + l.Logger.Trace().Msg("no ops value SKIP") + } + } + } + } + } + } + + // normalize latency values + for _, i := range cache.GetInstances() { + if !i.IsExportable() { + continue + } + for _, mKey := range latencyCacheMetrics { + m := cache.GetMetric(mKey) + if m != nil && m.IsExportable() { + if value, ok := m.GetValueFloat64(i); ok { + opsKey := strings.Replace(mKey, "cloud_bin_op_latency_average", opName, 1) + + // fetch from temp metrics + if ops := cache.GetMetric(opsKeyPrefix + opsKey); ops != nil { + if opsValue, ok := ops.GetValueFloat64(i); ok && opsValue != 0 { + err := m.SetValueFloat64(i, value/opsValue) + if err != nil { + l.Logger.Error().Err(err).Msg("error") + } + } else { + m.SetValueNAN(i) + } + } + } + } + } + } + return cache, nil +} diff --git a/cmd/collectors/restperf/plugins/fabricpool/fabricpool.go b/cmd/collectors/restperf/plugins/fabricpool/fabricpool.go index 695464c7d..3c6be989c 100644 --- a/cmd/collectors/restperf/plugins/fabricpool/fabricpool.go +++ b/cmd/collectors/restperf/plugins/fabricpool/fabricpool.go @@ -1,19 +1,35 @@ package fabricpool import ( + "github.com/netapp/harvest/v2/cmd/collectors" "github.com/netapp/harvest/v2/cmd/poller/plugin" "github.com/netapp/harvest/v2/pkg/matrix" + "strconv" "strings" ) type FabricPool struct { *plugin.AbstractPlugin + includeConstituents bool } func New(p *plugin.AbstractPlugin) plugin.Plugin { return &FabricPool{AbstractPlugin: p} } +func (f *FabricPool) Init() error { + err := f.InitAbc() + if err != nil { + return err + } + if val := f.Params.GetChildContentS("include_constituents"); val != "" { + if boolValue, err := strconv.ParseBool(val); err == nil { + f.includeConstituents = boolValue + } + } + return nil +} + // Run converts Rest lowercase metric names to uppercase to match ZapiPerf func (f *FabricPool) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, error) { data := dataMap[f.Object] @@ -27,5 +43,9 @@ func (f *FabricPool) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, e } } - return nil, nil + cache, err := collectors.GetFlexGroupFabricPoolMetrics(dataMap, f.Object, "cloud_bin_op", f.includeConstituents, f.Logger) + if err != nil { + return nil, err + } + return []*matrix.Matrix{cache}, nil } diff --git a/cmd/collectors/zapiperf/plugins/fabricpool/fabricpool.go b/cmd/collectors/zapiperf/plugins/fabricpool/fabricpool.go new file mode 100644 index 000000000..e171c8cd8 --- /dev/null +++ b/cmd/collectors/zapiperf/plugins/fabricpool/fabricpool.go @@ -0,0 +1,38 @@ +package fabricpool + +import ( + "github.com/netapp/harvest/v2/cmd/collectors" + "github.com/netapp/harvest/v2/cmd/poller/plugin" + "github.com/netapp/harvest/v2/pkg/matrix" + "strconv" +) + +type FabricPool struct { + *plugin.AbstractPlugin + includeConstituents bool +} + +func New(p *plugin.AbstractPlugin) plugin.Plugin { + return &FabricPool{AbstractPlugin: p} +} + +func (f *FabricPool) Init() error { + err := f.InitAbc() + if err != nil { + return err + } + if val := f.Params.GetChildContentS("include_constituents"); val != "" { + if boolValue, err := strconv.ParseBool(val); err == nil { + f.includeConstituents = boolValue + } + } + return nil +} + +func (f *FabricPool) Run(dataMap map[string]*matrix.Matrix) ([]*matrix.Matrix, error) { + cache, err := collectors.GetFlexGroupFabricPoolMetrics(dataMap, f.Object, "cloud_bin_operation", f.includeConstituents, f.Logger) + if err != nil { + return nil, err + } + return []*matrix.Matrix{cache}, nil +} diff --git a/cmd/collectors/zapiperf/zapiperf.go b/cmd/collectors/zapiperf/zapiperf.go index 07ee1e0ae..721f10eeb 100644 --- a/cmd/collectors/zapiperf/zapiperf.go +++ b/cmd/collectors/zapiperf/zapiperf.go @@ -28,6 +28,7 @@ import ( "errors" "github.com/netapp/harvest/v2/cmd/collectors/zapiperf/plugins/disk" "github.com/netapp/harvest/v2/cmd/collectors/zapiperf/plugins/externalserviceoperation" + "github.com/netapp/harvest/v2/cmd/collectors/zapiperf/plugins/fabricpool" "github.com/netapp/harvest/v2/cmd/collectors/zapiperf/plugins/fcp" "github.com/netapp/harvest/v2/cmd/collectors/zapiperf/plugins/fcvi" "github.com/netapp/harvest/v2/cmd/collectors/zapiperf/plugins/headroom" @@ -123,6 +124,8 @@ func (z *ZapiPerf) LoadPlugin(kind string, abc *plugin.AbstractPlugin) plugin.Pl return nic.New(abc) case "Fcp": return fcp.New(abc) + case "FabricPool": + return fabricpool.New(abc) case "Headroom": return headroom.New(abc) case "Volume": diff --git a/conf/restperf/9.12.0/wafl_comp_aggr_vol_bin.yaml b/conf/restperf/9.12.0/wafl_comp_aggr_vol_bin.yaml index ad6e97149..52b053130 100644 --- a/conf/restperf/9.12.0/wafl_comp_aggr_vol_bin.yaml +++ b/conf/restperf/9.12.0/wafl_comp_aggr_vol_bin.yaml @@ -11,7 +11,8 @@ counters: - cloud_bin_op_latency_average plugins: - - FabricPool + - FabricPool: + - include_constituents: false export_options: instance_keys: diff --git a/conf/zapiperf/cdot/9.8.0/wafl_comp_aggr_vol_bin.yaml b/conf/zapiperf/cdot/9.8.0/wafl_comp_aggr_vol_bin.yaml index ec6628305..d9659c119 100644 --- a/conf/zapiperf/cdot/9.8.0/wafl_comp_aggr_vol_bin.yaml +++ b/conf/zapiperf/cdot/9.8.0/wafl_comp_aggr_vol_bin.yaml @@ -12,6 +12,10 @@ counters: - vol_name => volume - vserver_name => svm +plugins: + - FabricPool: + - include_constituents: false + export_options: instance_keys: - cloud_target diff --git a/grafana/dashboards/cmode/volume.json b/grafana/dashboards/cmode/volume.json index 9c01eb836..78f784d34 100644 --- a/grafana/dashboards/cmode/volume.json +++ b/grafana/dashboards/cmode/volume.json @@ -4983,7 +4983,7 @@ "expr": "topk($TopResources, fabricpool_cloud_bin_op_latency_average{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",svm=~\"$SVM\",volume=~\"$TopCloudBinOpGetLatency\", metric=\"GET\"})", "hide": false, "interval": "", - "legendFormat": "{{volume}} ", + "legendFormat": "{{svm}} - {{volume}}", "refId": "A" } ], @@ -5076,7 +5076,7 @@ "expr": "topk($TopResources, fabricpool_cloud_bin_operation{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",svm=~\"$SVM\",volume=~\"$TopCloudBinOperationGet\", metric=\"GET\"})", "hide": false, "interval": "", - "legendFormat": "{{volume}} ", + "legendFormat": "{{svm}} - {{volume}}", "refId": "A" } ], @@ -5169,7 +5169,7 @@ "expr": "topk($TopResources, fabricpool_cloud_bin_op_latency_average{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",svm=~\"$SVM\",volume=~\"$TopCloudBinOpPutLatency\", metric=\"PUT\"})", "hide": false, "interval": "", - "legendFormat": "{{volume}} ", + "legendFormat": "{{svm}} - {{volume}}", "refId": "A" } ], @@ -5262,7 +5262,7 @@ "expr": "topk($TopResources, fabricpool_cloud_bin_operation{datacenter=~\"$Datacenter\",cluster=~\"$Cluster\",svm=~\"$SVM\",volume=~\"$TopCloudBinOperationPut\", metric=\"PUT\"})", "hide": false, "interval": "", - "legendFormat": "{{volume}} ", + "legendFormat": "{{svm}} - {{volume}} ", "refId": "A" } ],