Skip to content

Commit

Permalink
smb: refactor collector (#1740)
Browse files Browse the repository at this point in the history
Signed-off-by: Jan-Otto Kröpke <[email protected]>
  • Loading branch information
jkroepke authored Nov 15, 2024
1 parent b209ab6 commit 6206b69
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 135 deletions.
6 changes: 6 additions & 0 deletions internal/collector/smb/const.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package smb

const (
currentOpenFileCount = "Current Open File Count"
treeConnectCount = "Tree Connect Count"
)
112 changes: 50 additions & 62 deletions internal/collector/smb/smb.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand All @@ -22,6 +24,8 @@ var ConfigDefaults = Config{}
type Collector struct {
config Config

perfDataCollector perfdata.Collector

treeConnectCount *prometheus.Desc
currentOpenFileCount *prometheus.Desc
}
Expand All @@ -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(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
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)
}

for _, instance := range data {
labelName := c.toLabelName(instance.Name)
if !strings.HasSuffix(labelName, "_total") {
continue
}

ch <- prometheus.MustNewConstMetric(
c.currentOpenFileCount,
prometheus.CounterValue,
instance.CurrentOpenFileCount,
)

ch <- prometheus.MustNewConstMetric(
c.treeConnectCount,
prometheus.CounterValue,
instance.TreeConnectCount,
)
data, ok := perfData[perftypes.EmptyInstance]
if !ok {
return errors.New("query for SMB Server Shares returned empty result set")
}

return nil
}
ch <- prometheus.MustNewConstMetric(
c.currentOpenFileCount,
prometheus.CounterValue,
data[currentOpenFileCount].FirstValue,
)

// 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, "__", "_")
ch <- prometheus.MustNewConstMetric(
c.treeConnectCount,
prometheus.CounterValue,
data[treeConnectCount].FirstValue,
)

return s
return nil
}
25 changes: 25 additions & 0 deletions internal/collector/smbclient/const.go
Original file line number Diff line number Diff line change
@@ -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"
)
Loading

0 comments on commit 6206b69

Please sign in to comment.