Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

smb: refactor collector #1740

Merged
merged 1 commit into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading