Skip to content

Commit

Permalink
chore: optimize iphlpapi
Browse files Browse the repository at this point in the history
Signed-off-by: Jan-Otto Kröpke <[email protected]>
  • Loading branch information
jkroepke committed Nov 17, 2024
1 parent 79bd244 commit e35968c
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 65 deletions.
3 changes: 2 additions & 1 deletion internal/collector/mssql/mssql_access_methods.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ const (
func (c *Collector) buildAccessMethods() error {
var err error

c.accessMethodsPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances))
counters := []string{
accessMethodsAUCleanupbatchesPerSec,
accessMethodsAUCleanupsPerSec,
Expand Down Expand Up @@ -162,7 +163,7 @@ func (c *Collector) buildAccessMethods() error {
for sqlInstance := range c.mssqlInstances {
c.accessMethodsPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "AccessMethods"), nil, counters)
if err != nil {
return fmt.Errorf("failed to create AccessMethods collector for isntance %s: %w", sqlInstance, err)
return fmt.Errorf("failed to create AccessMethods collector for instance %s: %w", sqlInstance, err)
}
}

Expand Down
3 changes: 2 additions & 1 deletion internal/collector/mssql/mssql_availability_replica.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const (
func (c *Collector) buildAvailabilityReplica() error {
var err error

c.availabilityReplicaPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances))
counters := []string{
availReplicaBytesReceivedFromReplicaPerSec,
availReplicaBytesSentToReplicaPerSec,
Expand All @@ -58,7 +59,7 @@ func (c *Collector) buildAvailabilityReplica() error {
for sqlInstance := range c.mssqlInstances {
c.availabilityReplicaPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "Availability Replica"), perfdata.InstanceAll, counters)
if err != nil {
return fmt.Errorf("failed to create AccessMethods collector for isntance %s: %w", sqlInstance, err)
return fmt.Errorf("failed to create Availability Replica collector for instance %s: %w", sqlInstance, err)
}
}

Expand Down
179 changes: 116 additions & 63 deletions internal/collector/mssql/mssql_buffer_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,19 @@
package mssql

import (
"errors"
"fmt"
"log/slog"
"time"

"github.com/prometheus-community/windows_exporter/internal/perfdata"
"github.com/prometheus-community/windows_exporter/pkg/types"
"github.com/prometheus/client_golang/prometheus"
)

type collectorBufferManager struct {
bufManPerfDataCollectors map[string]*perfdata.Collector

// Win32_PerfRawData_{instance}_SQLServerBufferManager
bufManBackgroundwriterpages *prometheus.Desc
bufManBuffercachehits *prometheus.Desc
bufManBuffercachelookups *prometheus.Desc
Expand All @@ -38,9 +41,55 @@ type collectorBufferManager struct {
bufManTargetpages *prometheus.Desc
}

const (
BackgroundWriterPagesPerSec = "Background writer pages/sec"
BufferCacheHitRatio = "Buffer cache hit ratio"
BufferCacheHitRatioBase = "Buffer cache hit ratio base_Base"
CheckpointpagesPerSec = "Checkpoint pages/sec"
Databasepages = "Database pages"
Extensionallocatedpages = "Extension allocated pages"
Extensionfreepages = "Extension free pages"
Extensioninuseaspercentage = "Extension in use as percentage"
ExtensionoutstandingIOcounter = "Extension outstanding IO counter"
ExtensionpageevictionsPerSec = "Extension page evictions/sec"
ExtensionpagereadsPerSec = "Extension page reads/sec"
Extensionpageunreferencedtime = "Extension page unreferenced time"
ExtensionpagewritesPerSec = "Extension page writes/sec"
FreeliststallsPerSec = "Free list stalls/sec"
IntegralControllerSlope = "Integral Controller Slope"
LazywritesPerSec = "Lazy writes/sec"
Pagelifeexpectancy = "Page life expectancy"
PagelookupsPerSec = "Page lookups/sec"
PagereadsPerSec = "Page reads/sec"
PagewritesPerSec = "Page writes/sec"
ReadaheadpagesPerSec = "Readahead pages/sec"
ReadaheadtimePerSec = "Readahead time/sec"
TargetPages = "Target pages"
)

func (c *Collector) buildBufferManager() error {
var err error

c.bufManPerfDataCollectors = make(map[string]*perfdata.Collector, len(c.mssqlInstances))
counters := []string{
availReplicaBytesReceivedFromReplicaPerSec,
availReplicaBytesSentToReplicaPerSec,
availReplicaBytesSentToTransportPerSec,
availReplicaFlowControlPerSec,
availReplicaFlowControlTimeMSPerSec,
availReplicaReceivesFromReplicaPerSec,
availReplicaResentMessagesPerSec,
availReplicaSendsToReplicaPerSec,
availReplicaSendsToTransportPerSec,
}

for sqlInstance := range c.mssqlInstances {
c.bufManPerfDataCollectors[sqlInstance], err = perfdata.NewCollector(c.mssqlGetPerfObjectName(sqlInstance, "Buffer Manager"), nil, counters)
if err != nil {
return fmt.Errorf("failed to create Buffer Manager collector for instance %s: %w", sqlInstance, err)
}
}

// Win32_PerfRawData_{instance}_SQLServerBufferManager
c.bufManBackgroundwriterpages = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "bufman_background_writer_pages"),
"(BufferManager.Backgroundwriterpages)",
Expand Down Expand Up @@ -184,212 +233,216 @@ func (c *Collector) buildBufferManager() error {
}

func (c *Collector) collectBufferManager(ch chan<- prometheus.Metric) error {
return nil
}
errs := make([]error, 0, len(c.availabilityReplicaPerfDataCollectors))

func (c *Collector) closeBufferManager() error {
return nil
}
for sqlInstance, perfDataCollector := range c.availabilityReplicaPerfDataCollectors {
begin := time.Now()
success := 1.0
err := c.collectAvailabilityReplicaInstance(ch, sqlInstance, perfDataCollector)
duration := time.Since(begin).Seconds()

// Win32_PerfRawData_MSSQLSERVER_SQLServerBufferManager docs:
// - https://docs.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-buffer-manager-object
type mssqlBufferManager struct {
BackgroundWriterPagesPerSec float64 `perflib:"Background writer pages/sec"`
BufferCacheHitRatio float64 `perflib:"Buffer cache hit ratio"`
BufferCacheHitRatioBase float64 `perflib:"Buffer cache hit ratio base_Base"`
CheckpointpagesPerSec float64 `perflib:"Checkpoint pages/sec"`
Databasepages float64 `perflib:"Database pages"`
Extensionallocatedpages float64 `perflib:"Extension allocated pages"`
Extensionfreepages float64 `perflib:"Extension free pages"`
Extensioninuseaspercentage float64 `perflib:"Extension in use as percentage"`
ExtensionoutstandingIOcounter float64 `perflib:"Extension outstanding IO counter"`
ExtensionpageevictionsPerSec float64 `perflib:"Extension page evictions/sec"`
ExtensionpagereadsPerSec float64 `perflib:"Extension page reads/sec"`
Extensionpageunreferencedtime float64 `perflib:"Extension page unreferenced time"`
ExtensionpagewritesPerSec float64 `perflib:"Extension page writes/sec"`
FreeliststallsPerSec float64 `perflib:"Free list stalls/sec"`
IntegralControllerSlope float64 `perflib:"Integral Controller Slope"`
LazywritesPerSec float64 `perflib:"Lazy writes/sec"`
Pagelifeexpectancy float64 `perflib:"Page life expectancy"`
PagelookupsPerSec float64 `perflib:"Page lookups/sec"`
PagereadsPerSec float64 `perflib:"Page reads/sec"`
PagewritesPerSec float64 `perflib:"Page writes/sec"`
ReadaheadpagesPerSec float64 `perflib:"Readahead pages/sec"`
ReadaheadtimePerSec float64 `perflib:"Readahead time/sec"`
TargetPages float64 `perflib:"Target pages"`
}
if err != nil {
errs = append(errs, err)
success = 0.0

c.logger.Error(fmt.Sprintf("mssql class collector %s failed after %fs", SubCollectorBufferManager, duration),
slog.Any("err", err),
)
} else {
c.logger.Debug(fmt.Sprintf("mssql class collector %s succeeded after %fs.", SubCollectorBufferManager, duration))
}

func (c *Collector) collectBufferManager(ctx *types.ScrapeContext, logger *slog.Logger, ch chan<- prometheus.Metric, sqlInstance string) error {
var dst []mssqlBufferManager
ch <- prometheus.MustNewConstMetric(
c.mssqlScrapeDurationDesc,
prometheus.GaugeValue,
duration,
SubCollectorBufferManager, sqlInstance,
)
ch <- prometheus.MustNewConstMetric(
c.mssqlScrapeSuccessDesc,
prometheus.GaugeValue,
success,
SubCollectorBufferManager, sqlInstance,
)
}

logger.Debug(fmt.Sprintf("mssql_bufman collector iterating sql instance %s.", sqlInstance))
return errors.Join(errs...)
}

if err := v1.UnmarshalObject(ctx.PerfObjects[mssqlGetPerfObjectName(sqlInstance, "bufman")], &dst, logger); err != nil {
return err
func (c *Collector) collectBufferManagerInstance(ch chan<- prometheus.Metric, sqlInstance string, perfDataCollector *perfdata.Collector) error {
perfData, err := perfDataCollector.Collect()
if err != nil {
return fmt.Errorf("failed to collect %s metrics: %w", c.mssqlGetPerfObjectName(sqlInstance, "Buffer Manager"), err)
}

for _, v := range dst {
for _, data := range perfData {
ch <- prometheus.MustNewConstMetric(
c.bufManBackgroundwriterpages,
prometheus.CounterValue,
v.BackgroundWriterPagesPerSec,
data[BackgroundWriterPagesPerSec].FirstValue,
sqlInstance,
)

ch <- prometheus.MustNewConstMetric(
c.bufManBuffercachehits,
prometheus.GaugeValue,
v.BufferCacheHitRatio,
data[BufferCacheHitRatio].FirstValue,
sqlInstance,
)

ch <- prometheus.MustNewConstMetric(
c.bufManBuffercachelookups,
prometheus.GaugeValue,
v.BufferCacheHitRatioBase,
data[BufferCacheHitRatioBase].FirstValue,
sqlInstance,
)

ch <- prometheus.MustNewConstMetric(
c.bufManCheckpointpages,
prometheus.CounterValue,
v.CheckpointpagesPerSec,
data[CheckpointpagesPerSec].FirstValue,
sqlInstance,
)

ch <- prometheus.MustNewConstMetric(
c.bufManDatabasepages,
prometheus.GaugeValue,
v.Databasepages,
data[Databasepages].FirstValue,
sqlInstance,
)

ch <- prometheus.MustNewConstMetric(
c.bufManExtensionallocatedpages,
prometheus.GaugeValue,
v.Extensionallocatedpages,
data[Extensionallocatedpages].FirstValue,
sqlInstance,
)

ch <- prometheus.MustNewConstMetric(
c.bufManExtensionfreepages,
prometheus.GaugeValue,
v.Extensionfreepages,
data[Extensionfreepages].FirstValue,
sqlInstance,
)

ch <- prometheus.MustNewConstMetric(
c.bufManExtensioninuseaspercentage,
prometheus.GaugeValue,
v.Extensioninuseaspercentage,
data[Extensioninuseaspercentage].FirstValue,
sqlInstance,
)

ch <- prometheus.MustNewConstMetric(
c.bufManExtensionoutstandingIOcounter,
prometheus.GaugeValue,
v.ExtensionoutstandingIOcounter,
data[ExtensionoutstandingIOcounter].FirstValue,
sqlInstance,
)

ch <- prometheus.MustNewConstMetric(
c.bufManExtensionpageevictions,
prometheus.CounterValue,
v.ExtensionpageevictionsPerSec,
data[ExtensionpageevictionsPerSec].FirstValue,
sqlInstance,
)

ch <- prometheus.MustNewConstMetric(
c.bufManExtensionpagereads,
prometheus.CounterValue,
v.ExtensionpagereadsPerSec,
data[ExtensionpagereadsPerSec].FirstValue,
sqlInstance,
)

ch <- prometheus.MustNewConstMetric(
c.bufManExtensionpageunreferencedtime,
prometheus.GaugeValue,
v.Extensionpageunreferencedtime,
data[Extensionpageunreferencedtime].FirstValue,
sqlInstance,
)

ch <- prometheus.MustNewConstMetric(
c.bufManExtensionpagewrites,
prometheus.CounterValue,
v.ExtensionpagewritesPerSec,
data[ExtensionpagewritesPerSec].FirstValue,
sqlInstance,
)

ch <- prometheus.MustNewConstMetric(
c.bufManFreeliststalls,
prometheus.CounterValue,
v.FreeliststallsPerSec,
data[FreeliststallsPerSec].FirstValue,
sqlInstance,
)

ch <- prometheus.MustNewConstMetric(
c.bufManIntegralControllerSlope,
prometheus.GaugeValue,
v.IntegralControllerSlope,
data[IntegralControllerSlope].FirstValue,
sqlInstance,
)

ch <- prometheus.MustNewConstMetric(
c.bufManLazywrites,
prometheus.CounterValue,
v.LazywritesPerSec,
data[LazywritesPerSec].FirstValue,
sqlInstance,
)

ch <- prometheus.MustNewConstMetric(
c.bufManPagelifeexpectancy,
prometheus.GaugeValue,
v.Pagelifeexpectancy,
data[Pagelifeexpectancy].FirstValue,
sqlInstance,
)

ch <- prometheus.MustNewConstMetric(
c.bufManPagelookups,
prometheus.CounterValue,
v.PagelookupsPerSec,
data[PagelookupsPerSec].FirstValue,
sqlInstance,
)

ch <- prometheus.MustNewConstMetric(
c.bufManPagereads,
prometheus.CounterValue,
v.PagereadsPerSec,
data[PagereadsPerSec].FirstValue,
sqlInstance,
)

ch <- prometheus.MustNewConstMetric(
c.bufManPagewrites,
prometheus.CounterValue,
v.PagewritesPerSec,
data[PagewritesPerSec].FirstValue,
sqlInstance,
)

ch <- prometheus.MustNewConstMetric(
c.bufManReadaheadpages,
prometheus.CounterValue,
v.ReadaheadpagesPerSec,
data[ReadaheadpagesPerSec].FirstValue,
sqlInstance,
)

ch <- prometheus.MustNewConstMetric(
c.bufManReadaheadtime,
prometheus.CounterValue,
v.ReadaheadtimePerSec,
data[ReadaheadtimePerSec].FirstValue,
sqlInstance,
)

ch <- prometheus.MustNewConstMetric(
c.bufManTargetpages,
prometheus.GaugeValue,
v.TargetPages,
data[TargetPages].FirstValue,
sqlInstance,
)
}

return nil
}

func (c *Collector) closeBufferManager() {
for _, perfDataCollectors := range c.bufManPerfDataCollectors {
perfDataCollectors.Close()
}
}

0 comments on commit e35968c

Please sign in to comment.