smb: refactor collector (#1740)
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
This commit is contained in:
parent
b209ab6d6a
commit
6206b695c6
|
@ -0,0 +1,6 @@
|
|||
package smb
|
||||
|
||||
const (
|
||||
currentOpenFileCount = "Current Open File Count"
|
||||
treeConnectCount = "Tree Connect Count"
|
||||
)
|
|
@ -3,12 +3,14 @@
|
|||
package smb
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strings"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
||||
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
|
||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
@ -22,6 +24,8 @@ var ConfigDefaults = Config{}
|
|||
type Collector struct {
|
||||
config Config
|
||||
|
||||
perfDataCollector perfdata.Collector
|
||||
|
||||
treeConnectCount *prometheus.Desc
|
||||
currentOpenFileCount *prometheus.Desc
|
||||
}
|
||||
|
@ -47,89 +51,73 @@ func (c *Collector) GetName() string {
|
|||
}
|
||||
|
||||
func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
|
||||
return []string{
|
||||
"SMB Server Shares",
|
||||
}, nil
|
||||
return []string{}, nil
|
||||
}
|
||||
|
||||
func (c *Collector) Close(_ *slog.Logger) error {
|
||||
c.perfDataCollector.Close()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||
// desc creates a new prometheus description
|
||||
desc := func(metricName string, description string, labels ...string) *prometheus.Desc {
|
||||
return prometheus.NewDesc(
|
||||
prometheus.BuildFQName(types.Namespace, "smb", metricName),
|
||||
description,
|
||||
labels,
|
||||
nil,
|
||||
)
|
||||
var err error
|
||||
|
||||
c.perfDataCollector, err = perfdata.NewCollector(perfdata.V2, "SMB Server Shares", nil, []string{
|
||||
currentOpenFileCount,
|
||||
treeConnectCount,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create SMB Server Shares collector: %w", err)
|
||||
}
|
||||
|
||||
c.currentOpenFileCount = desc("server_shares_current_open_file_count", "Current total count open files on the SMB Server")
|
||||
c.treeConnectCount = desc("server_shares_tree_connect_count", "Count of user connections to the SMB Server")
|
||||
c.currentOpenFileCount = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "server_shares_current_open_file_count"),
|
||||
"Current total count open files on the SMB Server",
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
c.treeConnectCount = prometheus.NewDesc(
|
||||
prometheus.BuildFQName(types.Namespace, Name, "server_shares_tree_connect_count"),
|
||||
"Count of user connections to the SMB Server",
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Collect collects smb metrics and sends them to prometheus.
|
||||
func (c *Collector) Collect(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
|
||||
logger = logger.With(slog.String("collector", Name))
|
||||
if err := c.collectServerShares(ctx, logger, ch); err != nil {
|
||||
logger.Error("failed to collect server share metrics",
|
||||
slog.Any("err", err),
|
||||
)
|
||||
|
||||
return err
|
||||
func (c *Collector) Collect(_ *types.ScrapeContext, _ *slog.Logger, ch chan<- prometheus.Metric) error {
|
||||
if err := c.collectServerShares(ch); err != nil {
|
||||
return fmt.Errorf("failed to collect server share metrics: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Perflib: SMB Server Shares.
|
||||
type perflibServerShares struct {
|
||||
Name string
|
||||
|
||||
CurrentOpenFileCount float64 `perflib:"Current Open File Count"`
|
||||
TreeConnectCount float64 `perflib:"Tree Connect Count"`
|
||||
func (c *Collector) collectServerShares(ch chan<- prometheus.Metric) error {
|
||||
perfData, err := c.perfDataCollector.Collect()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to collect SMB Server Shares metrics: %w", err)
|
||||
}
|
||||
|
||||
func (c *Collector) collectServerShares(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
|
||||
logger = logger.With(slog.String("collector", Name))
|
||||
|
||||
var data []perflibServerShares
|
||||
|
||||
if err := v1.UnmarshalObject(ctx.PerfObjects["SMB Server Shares"], &data, logger); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, instance := range data {
|
||||
labelName := c.toLabelName(instance.Name)
|
||||
if !strings.HasSuffix(labelName, "_total") {
|
||||
continue
|
||||
data, ok := perfData[perftypes.EmptyInstance]
|
||||
if !ok {
|
||||
return errors.New("query for SMB Server Shares returned empty result set")
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.currentOpenFileCount,
|
||||
prometheus.CounterValue,
|
||||
instance.CurrentOpenFileCount,
|
||||
data[currentOpenFileCount].FirstValue,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.treeConnectCount,
|
||||
prometheus.CounterValue,
|
||||
instance.TreeConnectCount,
|
||||
data[treeConnectCount].FirstValue,
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// toLabelName converts strings to lowercase and replaces all whitespaces and dots with underscores.
|
||||
func (c *Collector) toLabelName(name string) string {
|
||||
s := strings.ReplaceAll(strings.Join(strings.Fields(strings.ToLower(name)), "_"), ".", "_")
|
||||
s = strings.ReplaceAll(s, "__", "_")
|
||||
|
||||
return s
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package smbclient
|
||||
|
||||
const (
|
||||
AvgDataQueueLength = "Avg. Data Queue Length"
|
||||
AvgReadQueueLength = "Avg. Read Queue Length"
|
||||
AvgSecPerRead = "Avg. sec/Read"
|
||||
AvgSecPerWrite = "Avg. sec/Write"
|
||||
AvgSecPerDataRequest = "Avg. sec/Data Request"
|
||||
AvgWriteQueueLength = "Avg. Write Queue Length"
|
||||
CreditStallsPerSec = "Credit Stalls/sec"
|
||||
CurrentDataQueueLength = "Current Data Queue Length"
|
||||
DataBytesPerSec = "Data Bytes/sec"
|
||||
DataRequestsPerSec = "Data Requests/sec"
|
||||
MetadataRequestsPerSec = "Metadata Requests/sec"
|
||||
ReadBytesTransmittedViaSMBDirectPerSec = "Read Bytes transmitted via SMB Direct/sec"
|
||||
ReadBytesPerSec = "Read Bytes/sec"
|
||||
ReadRequestsTransmittedViaSMBDirectPerSec = "Read Requests transmitted via SMB Direct/sec"
|
||||
ReadRequestsPerSec = "Read Requests/sec"
|
||||
TurboIOReadsPerSec = "Turbo I/O Reads/sec"
|
||||
TurboIOWritesPerSec = "Turbo I/O Writes/sec"
|
||||
WriteBytesTransmittedViaSMBDirectPerSec = "Write Bytes transmitted via SMB Direct/sec"
|
||||
WriteBytesPerSec = "Write Bytes/sec"
|
||||
WriteRequestsTransmittedViaSMBDirectPerSec = "Write Requests transmitted via SMB Direct/sec"
|
||||
WriteRequestsPerSec = "Write Requests/sec"
|
||||
)
|
|
@ -3,13 +3,14 @@
|
|||
package smbclient
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strings"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
"github.com/prometheus-community/windows_exporter/internal/mi"
|
||||
"github.com/prometheus-community/windows_exporter/internal/perfdata"
|
||||
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
|
||||
v1 "github.com/prometheus-community/windows_exporter/internal/perfdata/v1"
|
||||
"github.com/prometheus-community/windows_exporter/internal/types"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
@ -25,6 +26,8 @@ var ConfigDefaults = Config{}
|
|||
type Collector struct {
|
||||
config Config
|
||||
|
||||
perfDataCollector perfdata.Collector
|
||||
|
||||
readBytesTotal *prometheus.Desc
|
||||
readBytesTransmittedViaSMBDirectTotal *prometheus.Desc
|
||||
readRequestQueueSecsTotal *prometheus.Desc
|
||||
|
@ -70,9 +73,7 @@ func (c *Collector) GetName() string {
|
|||
}
|
||||
|
||||
func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
|
||||
return []string{
|
||||
"SMB Client Shares",
|
||||
}, nil
|
||||
return []string{}, nil
|
||||
}
|
||||
|
||||
func (c *Collector) Close(_ *slog.Logger) error {
|
||||
|
@ -80,10 +81,39 @@ func (c *Collector) Close(_ *slog.Logger) error {
|
|||
}
|
||||
|
||||
func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
||||
var err error
|
||||
|
||||
c.perfDataCollector, err = perfdata.NewCollector(perfdata.V2, "SMB Client Shares", nil, []string{
|
||||
AvgDataQueueLength,
|
||||
AvgReadQueueLength,
|
||||
AvgSecPerRead,
|
||||
AvgSecPerWrite,
|
||||
AvgSecPerDataRequest,
|
||||
AvgWriteQueueLength,
|
||||
CreditStallsPerSec,
|
||||
CurrentDataQueueLength,
|
||||
DataBytesPerSec,
|
||||
DataRequestsPerSec,
|
||||
MetadataRequestsPerSec,
|
||||
ReadBytesTransmittedViaSMBDirectPerSec,
|
||||
ReadBytesPerSec,
|
||||
ReadRequestsTransmittedViaSMBDirectPerSec,
|
||||
ReadRequestsPerSec,
|
||||
TurboIOReadsPerSec,
|
||||
TurboIOWritesPerSec,
|
||||
WriteBytesTransmittedViaSMBDirectPerSec,
|
||||
WriteBytesPerSec,
|
||||
WriteRequestsTransmittedViaSMBDirectPerSec,
|
||||
WriteRequestsPerSec,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create SMB Client Shares collector: %w", err)
|
||||
}
|
||||
|
||||
// desc creates a new prometheus description
|
||||
desc := func(metricName string, description string, labels []string) *prometheus.Desc {
|
||||
return prometheus.NewDesc(
|
||||
prometheus.BuildFQName(types.Namespace, "smbclient", metricName),
|
||||
prometheus.BuildFQName(types.Namespace, Name, metricName),
|
||||
description,
|
||||
labels,
|
||||
nil,
|
||||
|
@ -179,68 +209,30 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
|
|||
}
|
||||
|
||||
// Collect collects smb client metrics and sends them to prometheus.
|
||||
func (c *Collector) Collect(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
|
||||
logger = logger.With(slog.String("collector", Name))
|
||||
if err := c.collectClientShares(ctx, logger, ch); err != nil {
|
||||
logger.Error("Error in ClientShares",
|
||||
slog.Any("err", err),
|
||||
)
|
||||
|
||||
func (c *Collector) Collect(_ *types.ScrapeContext, _ *slog.Logger, ch chan<- prometheus.Metric) error {
|
||||
if err := c.collectClientShares(ch); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Perflib: SMB Client Shares.
|
||||
type perflibClientShares struct {
|
||||
Name string
|
||||
|
||||
AvgDataQueueLength float64 `perflib:"Avg. Data Queue Length"`
|
||||
AvgReadQueueLength float64 `perflib:"Avg. Read Queue Length"`
|
||||
AvgSecPerRead float64 `perflib:"Avg. sec/Read"`
|
||||
AvgSecPerWrite float64 `perflib:"Avg. sec/Write"`
|
||||
AvgSecPerDataRequest float64 `perflib:"Avg. sec/Data Request"`
|
||||
AvgWriteQueueLength float64 `perflib:"Avg. Write Queue Length"`
|
||||
CreditStallsPerSec float64 `perflib:"Credit Stalls/sec"`
|
||||
CurrentDataQueueLength float64 `perflib:"Current Data Queue Length"`
|
||||
DataBytesPerSec float64 `perflib:"Data Bytes/sec"`
|
||||
DataRequestsPerSec float64 `perflib:"Data Requests/sec"`
|
||||
MetadataRequestsPerSec float64 `perflib:"Metadata Requests/sec"`
|
||||
ReadBytesTransmittedViaSMBDirectPerSec float64 `perflib:"Read Bytes transmitted via SMB Direct/sec"`
|
||||
ReadBytesPerSec float64 `perflib:"Read Bytes/sec"`
|
||||
ReadRequestsTransmittedViaSMBDirectPerSec float64 `perflib:"Read Requests transmitted via SMB Direct/sec"`
|
||||
ReadRequestsPerSec float64 `perflib:"Read Requests/sec"`
|
||||
TurboIOReadsPerSec float64 `perflib:"Turbo I/O Reads/sec"`
|
||||
TurboIOWritesPerSec float64 `perflib:"Turbo I/O Writes/sec"`
|
||||
WriteBytesTransmittedViaSMBDirectPerSec float64 `perflib:"Write Bytes transmitted via SMB Direct/sec"`
|
||||
WriteBytesPerSec float64 `perflib:"Write Bytes/sec"`
|
||||
WriteRequestsTransmittedViaSMBDirectPerSec float64 `perflib:"Write Requests transmitted via SMB Direct/sec"`
|
||||
WriteRequestsPerSec float64 `perflib:"Write Requests/sec"`
|
||||
func (c *Collector) collectClientShares(ch chan<- prometheus.Metric) error {
|
||||
perfData, err := c.perfDataCollector.Collect()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to collect SMB Client Shares metrics: %w", err)
|
||||
}
|
||||
|
||||
func (c *Collector) collectClientShares(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric) error {
|
||||
logger = logger.With(slog.String("collector", Name))
|
||||
|
||||
var data []perflibClientShares
|
||||
|
||||
if err := v1.UnmarshalObject(ctx.PerfObjects["SMB Client Shares"], &data, logger); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, instance := range data {
|
||||
if instance.Name == "_Total" {
|
||||
continue
|
||||
}
|
||||
|
||||
parsed := strings.FieldsFunc(instance.Name, func(r rune) bool { return r == '\\' })
|
||||
for name, data := range perfData {
|
||||
parsed := strings.FieldsFunc(name, func(r rune) bool { return r == '\\' })
|
||||
serverValue := parsed[0]
|
||||
shareValue := parsed[1]
|
||||
|
||||
// Request time spent on queue. Convert from ticks to seconds.
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.requestQueueSecsTotal,
|
||||
prometheus.CounterValue,
|
||||
instance.AvgDataQueueLength*perftypes.TicksToSecondScaleFactor,
|
||||
data[AvgDataQueueLength].FirstValue*perftypes.TicksToSecondScaleFactor,
|
||||
serverValue, shareValue,
|
||||
)
|
||||
|
||||
|
@ -248,28 +240,28 @@ func (c *Collector) collectClientShares(ctx *types.ScrapeContext, logger *slog.L
|
|||
ch <- prometheus.MustNewConstMetric(
|
||||
c.readRequestQueueSecsTotal,
|
||||
prometheus.CounterValue,
|
||||
instance.AvgReadQueueLength*perftypes.TicksToSecondScaleFactor,
|
||||
data[AvgReadQueueLength].FirstValue*perftypes.TicksToSecondScaleFactor,
|
||||
serverValue, shareValue,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.readSecsTotal,
|
||||
prometheus.CounterValue,
|
||||
instance.AvgSecPerRead*perftypes.TicksToSecondScaleFactor,
|
||||
data[AvgSecPerRead].FirstValue*perftypes.TicksToSecondScaleFactor,
|
||||
serverValue, shareValue,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.writeSecsTotal,
|
||||
prometheus.CounterValue,
|
||||
instance.AvgSecPerWrite*perftypes.TicksToSecondScaleFactor,
|
||||
data[AvgSecPerWrite].FirstValue*perftypes.TicksToSecondScaleFactor,
|
||||
serverValue, shareValue,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.requestSecs,
|
||||
prometheus.CounterValue,
|
||||
instance.AvgSecPerDataRequest*perftypes.TicksToSecondScaleFactor,
|
||||
data[AvgSecPerDataRequest].FirstValue*perftypes.TicksToSecondScaleFactor,
|
||||
serverValue, shareValue,
|
||||
)
|
||||
|
||||
|
@ -277,112 +269,112 @@ func (c *Collector) collectClientShares(ctx *types.ScrapeContext, logger *slog.L
|
|||
ch <- prometheus.MustNewConstMetric(
|
||||
c.writeRequestQueueSecsTotal,
|
||||
prometheus.CounterValue,
|
||||
instance.AvgWriteQueueLength*perftypes.TicksToSecondScaleFactor,
|
||||
data[AvgWriteQueueLength].FirstValue*perftypes.TicksToSecondScaleFactor,
|
||||
serverValue, shareValue,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.creditStallsTotal,
|
||||
prometheus.CounterValue,
|
||||
instance.CreditStallsPerSec,
|
||||
data[CreditStallsPerSec].FirstValue,
|
||||
serverValue, shareValue,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.currentDataQueued,
|
||||
prometheus.GaugeValue,
|
||||
instance.CurrentDataQueueLength,
|
||||
data[CurrentDataQueueLength].FirstValue,
|
||||
serverValue, shareValue,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.dataBytesTotal,
|
||||
prometheus.CounterValue,
|
||||
instance.DataBytesPerSec,
|
||||
data[DataBytesPerSec].FirstValue,
|
||||
serverValue, shareValue,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.dataRequestsTotal,
|
||||
prometheus.CounterValue,
|
||||
instance.DataRequestsPerSec,
|
||||
data[DataRequestsPerSec].FirstValue,
|
||||
serverValue, shareValue,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.metadataRequestsTotal,
|
||||
prometheus.CounterValue,
|
||||
instance.MetadataRequestsPerSec,
|
||||
data[MetadataRequestsPerSec].FirstValue,
|
||||
serverValue, shareValue,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.readBytesTransmittedViaSMBDirectTotal,
|
||||
prometheus.CounterValue,
|
||||
instance.ReadBytesTransmittedViaSMBDirectPerSec,
|
||||
data[ReadBytesTransmittedViaSMBDirectPerSec].FirstValue,
|
||||
serverValue, shareValue,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.readBytesTotal,
|
||||
prometheus.CounterValue,
|
||||
instance.ReadBytesPerSec,
|
||||
data[ReadBytesPerSec].FirstValue,
|
||||
serverValue, shareValue,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.readRequestsTransmittedViaSMBDirectTotal,
|
||||
prometheus.CounterValue,
|
||||
instance.ReadRequestsTransmittedViaSMBDirectPerSec,
|
||||
data[ReadRequestsTransmittedViaSMBDirectPerSec].FirstValue,
|
||||
serverValue, shareValue,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.readsTotal,
|
||||
prometheus.CounterValue,
|
||||
instance.ReadRequestsPerSec,
|
||||
data[ReadRequestsPerSec].FirstValue,
|
||||
serverValue, shareValue,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.turboIOReadsTotal,
|
||||
prometheus.CounterValue,
|
||||
instance.TurboIOReadsPerSec,
|
||||
data[TurboIOReadsPerSec].FirstValue,
|
||||
serverValue, shareValue,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.TurboIOWritesTotal,
|
||||
prometheus.CounterValue,
|
||||
instance.TurboIOWritesPerSec,
|
||||
data[TurboIOWritesPerSec].FirstValue,
|
||||
serverValue, shareValue,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.writeBytesTransmittedViaSMBDirectTotal,
|
||||
prometheus.CounterValue,
|
||||
instance.WriteBytesTransmittedViaSMBDirectPerSec,
|
||||
data[WriteBytesTransmittedViaSMBDirectPerSec].FirstValue,
|
||||
serverValue, shareValue,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.writeBytesTotal,
|
||||
prometheus.CounterValue,
|
||||
instance.WriteBytesPerSec,
|
||||
data[WriteBytesPerSec].FirstValue,
|
||||
serverValue, shareValue,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.writeRequestsTransmittedViaSMBDirectTotal,
|
||||
prometheus.CounterValue,
|
||||
instance.WriteRequestsTransmittedViaSMBDirectPerSec,
|
||||
data[WriteRequestsTransmittedViaSMBDirectPerSec].FirstValue,
|
||||
serverValue, shareValue,
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.writesTotal,
|
||||
prometheus.CounterValue,
|
||||
instance.WriteRequestsPerSec,
|
||||
data[WriteRequestsPerSec].FirstValue,
|
||||
serverValue, shareValue,
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue