Skip to content
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
20 changes: 10 additions & 10 deletions collector/fixtures/e2e-64k-page-output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1987,34 +1987,34 @@ node_ipvs_outgoing_packets_total 0
# HELP node_kernel_hung_tasks_total Total number of tasks that have been detected as hung since the system booted.
# TYPE node_kernel_hung_tasks_total counter
node_kernel_hung_tasks_total 42
# HELP node_ksmd_full_scans_total ksmd 'full_scans' file.
# HELP node_ksmd_full_scans_total How many times all mergeable areas have been scanned.
# TYPE node_ksmd_full_scans_total counter
node_ksmd_full_scans_total 323
# HELP node_ksmd_general_profit_bytes ksmd 'general_profit' file.
# HELP node_ksmd_general_profit_bytes How effective is KSM. ksm_saved_pages * sizeof(page) - (all_rmap_items) * sizeof(rmap_item)
# TYPE node_ksmd_general_profit_bytes gauge
node_ksmd_general_profit_bytes 1.04448e+06
# HELP node_ksmd_merge_across_nodes ksmd 'merge_across_nodes' file.
# HELP node_ksmd_merge_across_nodes Specifies if pages from different NUMA nodes can be merged.
# TYPE node_ksmd_merge_across_nodes gauge
node_ksmd_merge_across_nodes 1
# HELP node_ksmd_pages_shared ksmd 'pages_shared' file.
# HELP node_ksmd_pages_shared How many shared pages are being used.
# TYPE node_ksmd_pages_shared gauge
node_ksmd_pages_shared 1
# HELP node_ksmd_pages_sharing ksmd 'pages_sharing' file.
# HELP node_ksmd_pages_sharing How many more sites are sharing them i.e. how much saved.
# TYPE node_ksmd_pages_sharing gauge
node_ksmd_pages_sharing 255
# HELP node_ksmd_pages_to_scan ksmd 'pages_to_scan' file.
# HELP node_ksmd_pages_to_scan How many pages to scan before ksmd goes to sleep.
# TYPE node_ksmd_pages_to_scan gauge
node_ksmd_pages_to_scan 100
# HELP node_ksmd_pages_unshared ksmd 'pages_unshared' file.
# HELP node_ksmd_pages_unshared How many pages unique but repeatedly checked for merging.
# TYPE node_ksmd_pages_unshared gauge
node_ksmd_pages_unshared 0
# HELP node_ksmd_pages_volatile ksmd 'pages_volatile' file.
# HELP node_ksmd_pages_volatile How many pages changing too fast to be placed in a tree.
# TYPE node_ksmd_pages_volatile gauge
node_ksmd_pages_volatile 0
# HELP node_ksmd_run ksmd 'run' file.
# HELP node_ksmd_run The status of ksmd. stopped = 0, running = 1
# TYPE node_ksmd_run gauge
node_ksmd_run 1
# HELP node_ksmd_sleep_seconds ksmd 'sleep_millisecs' file.
# HELP node_ksmd_sleep_seconds How many seconds ksmd should sleep before next scan.
# TYPE node_ksmd_sleep_seconds gauge
node_ksmd_sleep_seconds 0.02
# HELP node_lnstat_allocs_total linux network cache stats
Expand Down
20 changes: 10 additions & 10 deletions collector/fixtures/e2e-output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2019,34 +2019,34 @@ node_ipvs_outgoing_packets_total 0
# HELP node_kernel_hung_tasks_total Total number of tasks that have been detected as hung since the system booted.
# TYPE node_kernel_hung_tasks_total counter
node_kernel_hung_tasks_total 42
# HELP node_ksmd_full_scans_total ksmd 'full_scans' file.
# HELP node_ksmd_full_scans_total How many times all mergeable areas have been scanned.
# TYPE node_ksmd_full_scans_total counter
node_ksmd_full_scans_total 323
# HELP node_ksmd_general_profit_bytes ksmd 'general_profit' file.
# HELP node_ksmd_general_profit_bytes How effective is KSM. ksm_saved_pages * sizeof(page) - (all_rmap_items) * sizeof(rmap_item)
# TYPE node_ksmd_general_profit_bytes gauge
node_ksmd_general_profit_bytes 1.04448e+06
# HELP node_ksmd_merge_across_nodes ksmd 'merge_across_nodes' file.
# HELP node_ksmd_merge_across_nodes Specifies if pages from different NUMA nodes can be merged.
# TYPE node_ksmd_merge_across_nodes gauge
node_ksmd_merge_across_nodes 1
# HELP node_ksmd_pages_shared ksmd 'pages_shared' file.
# HELP node_ksmd_pages_shared How many shared pages are being used.
# TYPE node_ksmd_pages_shared gauge
node_ksmd_pages_shared 1
# HELP node_ksmd_pages_sharing ksmd 'pages_sharing' file.
# HELP node_ksmd_pages_sharing How many more sites are sharing them i.e. how much saved.
# TYPE node_ksmd_pages_sharing gauge
node_ksmd_pages_sharing 255
# HELP node_ksmd_pages_to_scan ksmd 'pages_to_scan' file.
# HELP node_ksmd_pages_to_scan How many pages to scan before ksmd goes to sleep.
# TYPE node_ksmd_pages_to_scan gauge
node_ksmd_pages_to_scan 100
# HELP node_ksmd_pages_unshared ksmd 'pages_unshared' file.
# HELP node_ksmd_pages_unshared How many pages unique but repeatedly checked for merging.
# TYPE node_ksmd_pages_unshared gauge
node_ksmd_pages_unshared 0
# HELP node_ksmd_pages_volatile ksmd 'pages_volatile' file.
# HELP node_ksmd_pages_volatile How many pages changing too fast to be placed in a tree.
# TYPE node_ksmd_pages_volatile gauge
node_ksmd_pages_volatile 0
# HELP node_ksmd_run ksmd 'run' file.
# HELP node_ksmd_run The status of ksmd. stopped = 0, running = 1
# TYPE node_ksmd_run gauge
node_ksmd_run 1
# HELP node_ksmd_sleep_seconds ksmd 'sleep_millisecs' file.
# HELP node_ksmd_sleep_seconds How many seconds ksmd should sleep before next scan.
# TYPE node_ksmd_sleep_seconds gauge
node_ksmd_sleep_seconds 0.02
# HELP node_lnstat_allocs_total linux network cache stats
Expand Down
122 changes: 88 additions & 34 deletions collector/ksmd_linux.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2015 The Prometheus Authors
// Copyright The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
Expand All @@ -17,53 +17,93 @@ package collector

import (
"errors"
"fmt"
"log/slog"
"os"
"path/filepath"

"github.com/prometheus/client_golang/prometheus"
)

const ksmdCollectorSubsystem = "ksmd"

var (
ksmdFiles = []string{"full_scans", "general_profit", "merge_across_nodes", "pages_shared",
"pages_sharing", "pages_to_scan", "pages_unshared", "pages_volatile", "run",
"sleep_millisecs"}
ksmdFiles = []string{
"full_scans",
"general_profit",
"merge_across_nodes",
"pages_shared",
"pages_sharing",
"pages_to_scan",
"pages_unshared",
"pages_volatile",
"run",
"sleep_millisecs",
}

// Help text from https://docs.kernel.org/admin-guide/mm/ksm.html
ksmdFullScansDesc = prometheus.NewDesc(
prometheus.BuildFQName(namespace, ksmdCollectorSubsystem, "full_scans_total"),
"How many times all mergeable areas have been scanned.",
nil, nil,
)
ksmdGeneralProfitDesc = prometheus.NewDesc(
prometheus.BuildFQName(namespace, ksmdCollectorSubsystem, "general_profit_bytes"),
"How effective is KSM. ksm_saved_pages * sizeof(page) - (all_rmap_items) * sizeof(rmap_item)",
nil, nil,
)
ksmdMergeAcrossNodesDesc = prometheus.NewDesc(
prometheus.BuildFQName(namespace, ksmdCollectorSubsystem, "merge_across_nodes"),
"Specifies if pages from different NUMA nodes can be merged.",
nil, nil,
)
ksmdPagesSharedDesc = prometheus.NewDesc(
prometheus.BuildFQName(namespace, ksmdCollectorSubsystem, "pages_shared"),
"How many shared pages are being used.",
nil, nil,
)
ksmdPagesSharingDesc = prometheus.NewDesc(
prometheus.BuildFQName(namespace, ksmdCollectorSubsystem, "pages_sharing"),
"How many more sites are sharing them i.e. how much saved.",
nil, nil,
)
ksmdPagesToScanDesc = prometheus.NewDesc(
prometheus.BuildFQName(namespace, ksmdCollectorSubsystem, "pages_to_scan"),
"How many pages to scan before ksmd goes to sleep.",
nil, nil,
)
ksmdPagesUnsharedDesc = prometheus.NewDesc(
prometheus.BuildFQName(namespace, ksmdCollectorSubsystem, "pages_unshared"),
"How many pages unique but repeatedly checked for merging.",
nil, nil,
)
ksmdPagesVolatileDesc = prometheus.NewDesc(
prometheus.BuildFQName(namespace, ksmdCollectorSubsystem, "pages_volatile"),
"How many pages changing too fast to be placed in a tree.",
nil, nil,
)
ksmdRunDesc = prometheus.NewDesc(
prometheus.BuildFQName(namespace, ksmdCollectorSubsystem, "run"),
"The status of ksmd. stopped = 0, running = 1",
nil, nil,
)
ksmdSleepSecondsDesc = prometheus.NewDesc(
prometheus.BuildFQName(namespace, ksmdCollectorSubsystem, "sleep_seconds"),
"How many seconds ksmd should sleep before next scan.",
nil, nil,
)
)

type ksmdCollector struct {
metricDescs map[string]*prometheus.Desc
logger *slog.Logger
logger *slog.Logger
}

func init() {
registerCollector("ksmd", defaultDisabled, NewKsmdCollector)
}

func getCanonicalMetricName(filename string) string {
switch filename {
case "full_scans":
return filename + "_total"
case "general_profit":
return "general_profit_bytes"
case "sleep_millisecs":
return "sleep_seconds"
default:
return filename
}
registerCollector(ksmdCollectorSubsystem, defaultDisabled, NewKsmdCollector)
}

// NewKsmdCollector returns a new Collector exposing kernel/system statistics.
func NewKsmdCollector(logger *slog.Logger) (Collector, error) {
subsystem := "ksmd"
descs := make(map[string]*prometheus.Desc)

for _, n := range ksmdFiles {
descs[n] = prometheus.NewDesc(
prometheus.BuildFQName(namespace, subsystem, getCanonicalMetricName(n)),
fmt.Sprintf("ksmd '%s' file.", n), nil, nil)
}
return &ksmdCollector{descs, logger}, nil
return &ksmdCollector{logger: logger}, nil
}

// Update implements Collector and exposes kernel and system statistics.
Expand All @@ -78,15 +118,29 @@ func (c *ksmdCollector) Update(ch chan<- prometheus.Metric) error {
return err
}

t := prometheus.GaugeValue
v := float64(val)
switch n {
case "full_scans":
t = prometheus.CounterValue
ch <- prometheus.MustNewConstMetric(ksmdFullScansDesc, prometheus.CounterValue, v)
case "general_profit":
ch <- prometheus.MustNewConstMetric(ksmdGeneralProfitDesc, prometheus.GaugeValue, v)
case "merge_across_nodes":
ch <- prometheus.MustNewConstMetric(ksmdMergeAcrossNodesDesc, prometheus.GaugeValue, v)
case "pages_shared":
ch <- prometheus.MustNewConstMetric(ksmdPagesSharedDesc, prometheus.GaugeValue, v)
case "pages_sharing":
ch <- prometheus.MustNewConstMetric(ksmdPagesSharingDesc, prometheus.GaugeValue, v)
case "pages_to_scan":
ch <- prometheus.MustNewConstMetric(ksmdPagesToScanDesc, prometheus.GaugeValue, v)
case "pages_unshared":
ch <- prometheus.MustNewConstMetric(ksmdPagesUnsharedDesc, prometheus.GaugeValue, v)
case "pages_volatile":
ch <- prometheus.MustNewConstMetric(ksmdPagesVolatileDesc, prometheus.GaugeValue, v)
case "run":
ch <- prometheus.MustNewConstMetric(ksmdRunDesc, prometheus.GaugeValue, v)
case "sleep_millisecs":
v /= 1000
ch <- prometheus.MustNewConstMetric(ksmdSleepSecondsDesc, prometheus.GaugeValue, v/1000)
}
ch <- prometheus.MustNewConstMetric(c.metricDescs[n], t, v)
}

return nil
Expand Down
Loading