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

pagefile: BREAKING: move paging metrics from os to dedicated collector (click PR for more information) #1735

Merged
merged 5 commits into from
Nov 14, 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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Name | Description | Enabled by default
[netframework](docs/collector.netframework.md) | .NET Framework metrics |
[net](docs/collector.net.md) | Network interface I/O | ✓
[os](docs/collector.os.md) | OS metrics (memory, processes, users) | ✓
[pagefile](docs/collector.pagefile.md) | pagefile metrics |
[perfdata](docs/collector.perfdata.md) | Custom perfdata metrics |
[physical_disk](docs/collector.physical_disk.md) | physical disk metrics | ✓
[printer](docs/collector.printer.md) | Printer metrics |
Expand Down
12 changes: 5 additions & 7 deletions docs/collector.os.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,11 @@ None

## Metrics

| Name | Description | Type | Labels |
|---------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------|------------------------------------------------------------------------|
| `windows_os_info` | Contains full product name & version in labels. Note that the `major_version` for Windows 11 is "10"; a build number greater than 22000 represents Windows 11. | gauge | `product`, `version`, `major_version`, `minor_version`, `build_number` |
| `windows_os_paging_limit_bytes` | Total number of bytes that can be stored in the operating system paging files. 0 (zero) indicates that there are no paging files | gauge | None |
| `windows_os_paging_free_bytes` | Number of bytes that can be mapped into the operating system paging files without causing any other pages to be swapped out | gauge | None |
| Name | Description | Type | Labels |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|-------|------------------------------------------------------------------------|
| `windows_os_hostname` | Labelled system hostname information as provided by ComputerSystem.DNSHostName and ComputerSystem.Domain | gauge | `domain`, `fqdn`, `hostname` |
| `windows_os_info` | Contains full product name & version in labels. Note that the `major_version` for Windows 11 is "10"; a build number greater than 22000 represents Windows 11. | gauge | `product`, `version`, `major_version`, `minor_version`, `build_number` |


### Example metric

```
Expand All @@ -36,4 +34,4 @@ windows_os_info{build_number="19045",major_version="10",minor_version="0",produc
_This collector does not yet have useful queries, we would appreciate your help adding them!_

## Alerting examples
_This collector does not yet have alerting examples, we would appreciate your help adding them!_
_This collector does not yet have alerting examples, we would appreciate your help adding them!_
38 changes: 38 additions & 0 deletions docs/collector.pagefile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# pagefile collector

The pagefile collector exposes metrics about the pagefile usage

|||
-|-
Metric name prefix | `pagefile`
Classes | [`Win32_OperatingSystem`](https://msdn.microsoft.com/en-us/library/aa394239)
Enabled by default? | Yes

## Flags

None

## Metrics

| Name | Description | Type | Labels |
|--------------------------------|-----------------------------------------------------------------------------------------------------------------------------|-------|--------|
| `windows_pagefile_free_bytes` | Number of bytes that can be mapped into the operating system paging files without causing any other pages to be swapped out | gauge | `file` |
| `windows_pagefile_limit_bytes` | Number of bytes that can be stored in the operating system paging files. 0 (zero) indicates that there are no paging files | gauge | `file` |


### Example metric

```
# HELP windows_pagefile_free_bytes OperatingSystem.FreeSpaceInPagingFiles
# TYPE windows_pagefile_free_bytes gauge
windows_pagefile_free_bytes{file="C:\\pagefile.sys"} 6.025797632e+09
# HELP windows_pagefile_limit_bytes OperatingSystem.SizeStoredInPagingFiles
# TYPE windows_pagefile_limit_bytes gauge
windows_pagefile_limit_bytes{file="C:\\pagefile.sys"} 6.442450944e+09
```

## Useful queries
_This collector does not yet have useful queries, we would appreciate your help adding them!_

## Alerting examples
_This collector does not yet have alerting examples, we would appreciate your help adding them!_
15 changes: 10 additions & 5 deletions internal/collector/os/os.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,14 @@ var ConfigDefaults = Config{}
type Collector struct {
config Config

hostname *prometheus.Desc
osInformation *prometheus.Desc
pagingFreeBytes *prometheus.Desc
hostname *prometheus.Desc
osInformation *prometheus.Desc

// pagingFreeBytes
// Deprecated: Use windows_paging_free_bytes instead.
pagingFreeBytes *prometheus.Desc
// pagingLimitBytes
// Deprecated: Use windows_paging_total_bytes instead.
pagingLimitBytes *prometheus.Desc

// users
Expand Down Expand Up @@ -151,13 +156,13 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
)
c.pagingLimitBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "paging_limit_bytes"),
"OperatingSystem.SizeStoredInPagingFiles",
"Deprecated: Use windows_pagefile_limit_bytes instead.",
nil,
nil,
)
c.pagingFreeBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "paging_free_bytes"),
"OperatingSystem.FreeSpaceInPagingFiles",
"Deprecated: Use windows_pagefile_free_bytes instead.",
nil,
nil,
)
Expand Down
5 changes: 5 additions & 0 deletions internal/collector/pagefile/const.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package pagefile

const (
usage = "% Usage"
)
136 changes: 136 additions & 0 deletions internal/collector/pagefile/pagefile.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
//go:build windows

package pagefile

import (
"fmt"
"log/slog"
"os"
"strings"

"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/headers/psapi"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/perfdata"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus/client_golang/prometheus"
)

const Name = "pagefile"

type Config struct{}

var ConfigDefaults = Config{}

// A Collector is a Prometheus Collector for WMI metrics.
type Collector struct {
config Config

perfDataCollector perfdata.Collector

pagingFreeBytes *prometheus.Desc
pagingLimitBytes *prometheus.Desc
}

func New(config *Config) *Collector {
if config == nil {
config = &ConfigDefaults
}

c := &Collector{
config: *config,
}

return c
}

func NewWithFlags(_ *kingpin.Application) *Collector {
return &Collector{}
}

func (c *Collector) GetName() string {
return Name
}

func (c *Collector) GetPerfCounter(_ *slog.Logger) ([]string, error) {
return []string{}, nil
}

func (c *Collector) Close(_ *slog.Logger) error {
return nil
}

func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
counters := []string{
usage,
}

var err error

c.perfDataCollector, err = perfdata.NewCollector(perfdata.V2, "Paging File", perfdata.AllInstances, counters)
if err != nil {
return fmt.Errorf("failed to create Paging File collector: %w", err)
}

c.pagingLimitBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "limit_bytes"),
"Number of bytes that can be stored in the operating system paging files. 0 (zero) indicates that there are no paging files",
[]string{"file"},
nil,
)

c.pagingFreeBytes = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "free_bytes"),
"Number of bytes that can be mapped into the operating system paging files without causing any other pages to be swapped out",
[]string{"file"},
nil,
)

return nil
}

// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(_ *types.ScrapeContext, _ *slog.Logger, ch chan<- prometheus.Metric) error {
return c.collectPaging(ch)
}

func (c *Collector) collectPaging(ch chan<- prometheus.Metric) error {
data, err := c.perfDataCollector.Collect()
if err != nil {
return fmt.Errorf("failed to collect Paging File metrics: %w", err)
}

gpi, err := psapi.GetPerformanceInfo()
if err != nil {
return err
}

for fileName, pageFile := range data {
fileString := strings.ReplaceAll(fileName, `\??\`, "")
file, err := os.Stat(fileString)

var fileSize float64

// For unknown reasons, Windows doesn't always create a page file. Continue collection rather than aborting.
if err == nil {
fileSize = float64(file.Size())
}

ch <- prometheus.MustNewConstMetric(
c.pagingFreeBytes,
prometheus.GaugeValue,
fileSize-(pageFile[usage].FirstValue*float64(gpi.PageSize)),
fileString,
)

ch <- prometheus.MustNewConstMetric(
c.pagingLimitBytes,
prometheus.GaugeValue,
fileSize,
fileString,
)
}

return nil
}
16 changes: 16 additions & 0 deletions internal/collector/pagefile/pagefile_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package pagefile_test

import (
"testing"

"github.com/prometheus-community/windows_exporter/internal/collector/pagefile"
"github.com/prometheus-community/windows_exporter/internal/testutils"
)

func BenchmarkCollector(b *testing.B) {
testutils.FuncBenchmarkCollector(b, pagefile.Name, pagefile.NewWithFlags)
}

func TestCollector(t *testing.T) {
testutils.TestCollector(t, pagefile.New, nil)
}
19 changes: 10 additions & 9 deletions internal/perfdata/v2/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package v2
import (
"errors"
"fmt"
"slices"
"strings"
"unsafe"

Expand All @@ -14,9 +15,10 @@ import (
)

type Collector struct {
object string
counters map[string]Counter
handle pdhQueryHandle
object string
counters map[string]Counter
handle pdhQueryHandle
totalCounterRequested bool
}

type Counter struct {
Expand All @@ -39,9 +41,10 @@ func NewCollector(object string, instances []string, counters []string) (*Collec
}

collector := &Collector{
object: object,
counters: make(map[string]Counter, len(counters)),
handle: handle,
object: object,
counters: make(map[string]Counter, len(counters)),
handle: handle,
totalCounterRequested: slices.Contains(instances, "_Total"),
}

for _, counterName := range counters {
Expand Down Expand Up @@ -166,12 +169,10 @@ func (c *Collector) Collect() (map[string]map[string]perftypes.CounterValues, er
metricType = prometheus.GaugeValue
}

_, isTotalCounterRequests := c.counters["_Total"]

for _, item := range items {
if item.RawValue.CStatus == PdhCstatusValidData || item.RawValue.CStatus == PdhCstatusNewData {
instanceName := windows.UTF16PtrToString(item.SzName)
if strings.HasSuffix(instanceName, "_Total") && !isTotalCounterRequests {
if strings.HasSuffix(instanceName, "_Total") && !c.totalCounterRequested {
continue
}

Expand Down
2 changes: 2 additions & 0 deletions pkg/collector/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import (
"github.com/prometheus-community/windows_exporter/internal/collector/netframework"
"github.com/prometheus-community/windows_exporter/internal/collector/nps"
"github.com/prometheus-community/windows_exporter/internal/collector/os"
"github.com/prometheus-community/windows_exporter/internal/collector/pagefile"
"github.com/prometheus-community/windows_exporter/internal/collector/perfdata"
"github.com/prometheus-community/windows_exporter/internal/collector/physical_disk"
"github.com/prometheus-community/windows_exporter/internal/collector/printer"
Expand Down Expand Up @@ -107,6 +108,7 @@ func NewWithConfig(config Config) *MetricCollectors {
collectors[netframework.Name] = netframework.New(&config.NetFramework)
collectors[nps.Name] = nps.New(&config.Nps)
collectors[os.Name] = os.New(&config.OS)
collectors[pagefile.Name] = pagefile.New(&config.Paging)
collectors[perfdata.Name] = perfdata.New(&config.PerfData)
collectors[physical_disk.Name] = physical_disk.New(&config.PhysicalDisk)
collectors[printer.Name] = printer.New(&config.Printer)
Expand Down
3 changes: 3 additions & 0 deletions pkg/collector/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"github.com/prometheus-community/windows_exporter/internal/collector/netframework"
"github.com/prometheus-community/windows_exporter/internal/collector/nps"
"github.com/prometheus-community/windows_exporter/internal/collector/os"
"github.com/prometheus-community/windows_exporter/internal/collector/pagefile"
"github.com/prometheus-community/windows_exporter/internal/collector/perfdata"
"github.com/prometheus-community/windows_exporter/internal/collector/physical_disk"
"github.com/prometheus-community/windows_exporter/internal/collector/printer"
Expand Down Expand Up @@ -79,6 +80,7 @@ type Config struct {
NetFramework netframework.Config `yaml:"net_framework"`
Nps nps.Config `yaml:"nps"`
OS os.Config `yaml:"os"`
Paging pagefile.Config `yaml:"paging"`
PerfData perfdata.Config `yaml:"perf_data"`
PhysicalDisk physical_disk.Config `yaml:"physical_disk"`
Printer printer.Config `yaml:"printer"`
Expand Down Expand Up @@ -132,6 +134,7 @@ var ConfigDefaults = Config{
NetFramework: netframework.ConfigDefaults,
Nps: nps.ConfigDefaults,
OS: os.ConfigDefaults,
Paging: pagefile.ConfigDefaults,
PerfData: perfdata.ConfigDefaults,
PhysicalDisk: physical_disk.ConfigDefaults,
Printer: printer.ConfigDefaults,
Expand Down
2 changes: 2 additions & 0 deletions pkg/collector/map.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"github.com/prometheus-community/windows_exporter/internal/collector/netframework"
"github.com/prometheus-community/windows_exporter/internal/collector/nps"
"github.com/prometheus-community/windows_exporter/internal/collector/os"
"github.com/prometheus-community/windows_exporter/internal/collector/pagefile"
"github.com/prometheus-community/windows_exporter/internal/collector/perfdata"
"github.com/prometheus-community/windows_exporter/internal/collector/physical_disk"
"github.com/prometheus-community/windows_exporter/internal/collector/printer"
Expand Down Expand Up @@ -89,6 +90,7 @@ var BuildersWithFlags = map[string]BuilderWithFlags[Collector]{
netframework.Name: NewBuilderWithFlags(netframework.NewWithFlags),
nps.Name: NewBuilderWithFlags(nps.NewWithFlags),
os.Name: NewBuilderWithFlags(os.NewWithFlags),
pagefile.Name: NewBuilderWithFlags(pagefile.NewWithFlags),
perfdata.Name: NewBuilderWithFlags(perfdata.NewWithFlags),
physical_disk.Name: NewBuilderWithFlags(physical_disk.NewWithFlags),
printer.Name: NewBuilderWithFlags(printer.NewWithFlags),
Expand Down
Loading