Skip to content

Commit

Permalink
support custom /proc path
Browse files Browse the repository at this point in the history
  • Loading branch information
oif committed Jul 20, 2021
1 parent 8331226 commit 6e7a107
Show file tree
Hide file tree
Showing 10 changed files with 39 additions and 35 deletions.
10 changes: 7 additions & 3 deletions pkg/systemstatsmonitor/cpu_collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,17 @@ type cpuCollector struct {
mSystemInterruptsTotal *metrics.Int64Metric
mSystemCPUStat *metrics.Float64Metric // per-cpu time from /proc/stats

config *ssmtypes.CPUStatsConfig
config *ssmtypes.CPUStatsConfig
procPath string

lastUsageTime map[string]float64
}

func NewCPUCollectorOrDie(cpuConfig *ssmtypes.CPUStatsConfig) *cpuCollector {
cc := cpuCollector{config: cpuConfig}
func NewCPUCollectorOrDie(cpuConfig *ssmtypes.CPUStatsConfig, procPath string) *cpuCollector {
cc := cpuCollector{
config: cpuConfig,
procPath: procPath,
}

var err error
cc.mRunnableTaskCount, err = metrics.NewFloat64Metric(
Expand Down
2 changes: 1 addition & 1 deletion pkg/systemstatsmonitor/cpu_collector_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func (cc *cpuCollector) recordLoad() {
}

func (cc *cpuCollector) recordSystemStats() {
fs, err := procfs.NewFS("/proc")
fs, err := procfs.NewFS(cc.procPath)
stats, err := fs.Stat()
if err != nil {
glog.Errorf("Failed to retrieve cpu/process stats: %v", err)
Expand Down
6 changes: 4 additions & 2 deletions pkg/systemstatsmonitor/net_collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@ import (

type netCollector struct {
config *ssmtypes.NetStatsConfig
procPath string
recorder *ifaceStatRecorder
}

func NewNetCollectorOrDie(netConfig *ssmtypes.NetStatsConfig) *netCollector {
func NewNetCollectorOrDie(netConfig *ssmtypes.NetStatsConfig, procPath string) *netCollector {
nc := netCollector{
config: netConfig,
procPath: procPath,
recorder: newIfaceStatRecorder(),
}

Expand Down Expand Up @@ -207,7 +209,7 @@ func (nc *netCollector) mustRegisterMetric(metricID metrics.MetricID, descriptio
}

func (nc *netCollector) recordNetDev() {
fs, err := procfs.NewFS("/proc")
fs, err := procfs.NewFS(nc.procPath)
stats, err := fs.NetDev()
if err != nil {
glog.Errorf("Failed to retrieve net dev stat: %v", err)
Expand Down
13 changes: 9 additions & 4 deletions pkg/systemstatsmonitor/osfeature_collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package systemstatsmonitor
import (
"encoding/json"
"io/ioutil"
"path/filepath"
"strconv"
"strings"

Expand All @@ -27,11 +28,15 @@ import (

type osFeatureCollector struct {
config *ssmtypes.OSFeatureStatsConfig
procPath string
osFeature *metrics.Int64Metric
}

func NewOsFeatureCollectorOrDie(osFeatureConfig *ssmtypes.OSFeatureStatsConfig) *osFeatureCollector {
oc := osFeatureCollector{config: osFeatureConfig}
func NewOsFeatureCollectorOrDie(osFeatureConfig *ssmtypes.OSFeatureStatsConfig, procPath string) *osFeatureCollector {
oc := osFeatureCollector{
config: osFeatureConfig,
procPath: procPath,
}
var err error
// Use metrics.Last aggregation method to ensure the metric is a guage metric.
if osFeatureConfig.MetricsConfigs["system/os_feature"].DisplayName != "" {
Expand Down Expand Up @@ -145,12 +150,12 @@ func (ofc *osFeatureCollector) collect() {
if ofc == nil || ofc.osFeature == nil {
return
}
cmdlineArgs, err := system.CmdlineArgs()
cmdlineArgs, err := system.CmdlineArgs(filepath.Join(ofc.procPath, "/cmdline"))
if err != nil {
glog.Fatalf("Error retrieving cmdline args: %v", err)
}
ofc.recordFeaturesFromCmdline(cmdlineArgs)
modules, err := system.Modules()
modules, err := system.Modules(filepath.Join(ofc.procPath, "/modules"))
if err != nil {
glog.Fatalf("Error retrieving kernel modules: %v", err)
}
Expand Down
6 changes: 3 additions & 3 deletions pkg/systemstatsmonitor/system_stats_monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func NewSystemStatsMonitorOrDie(configPath string) types.Monitor {
}

if len(ssm.config.CPUConfig.MetricsConfigs) > 0 {
ssm.cpuCollector = NewCPUCollectorOrDie(&ssm.config.CPUConfig)
ssm.cpuCollector = NewCPUCollectorOrDie(&ssm.config.CPUConfig, ssm.config.ProcPath)
}
if len(ssm.config.DiskConfig.MetricsConfigs) > 0 {
ssm.diskCollector = NewDiskCollectorOrDie(&ssm.config.DiskConfig)
Expand All @@ -96,10 +96,10 @@ func NewSystemStatsMonitorOrDie(configPath string) types.Monitor {
ssm.config.OsFeatureConfig.KnownModulesConfigPath = filepath.Join(filepath.Dir(configPath),
ssm.config.OsFeatureConfig.KnownModulesConfigPath)
}
ssm.osFeatureCollector = NewOsFeatureCollectorOrDie(&ssm.config.OsFeatureConfig)
ssm.osFeatureCollector = NewOsFeatureCollectorOrDie(&ssm.config.OsFeatureConfig, ssm.config.ProcPath)
}
if len(ssm.config.NetConfig.MetricsConfigs) > 0 {
ssm.netCollector = NewNetCollectorOrDie(&ssm.config.NetConfig)
ssm.netCollector = NewNetCollectorOrDie(&ssm.config.NetConfig, ssm.config.ProcPath)
}
return &ssm
}
Expand Down
9 changes: 9 additions & 0 deletions pkg/systemstatsmonitor/types/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ package types

import (
"fmt"
"os"
"time"
)

var (
defaultInvokeIntervalString = (60 * time.Second).String()
defaultlsblkTimeoutString = (5 * time.Second).String()
defaultKnownModulesConfigPath = "guestosconfig/known-modules.json"
defaultProcPath = "/proc"
)

type MetricConfig struct {
Expand Down Expand Up @@ -69,13 +71,17 @@ type SystemStatsConfig struct {
NetConfig NetStatsConfig `json:"net"`
InvokeIntervalString string `json:"invokeInterval"`
InvokeInterval time.Duration `json:"-"`
ProcPath string `json:"procPath"`
}

// ApplyConfiguration applies default configurations.
func (ssc *SystemStatsConfig) ApplyConfiguration() error {
if ssc.InvokeIntervalString == "" {
ssc.InvokeIntervalString = defaultInvokeIntervalString
}
if ssc.ProcPath == "" {
ssc.ProcPath = defaultProcPath
}
if ssc.DiskConfig.LsblkTimeoutString == "" {
ssc.DiskConfig.LsblkTimeoutString = defaultlsblkTimeoutString
}
Expand All @@ -101,6 +107,9 @@ func (ssc *SystemStatsConfig) Validate() error {
if ssc.InvokeInterval <= time.Duration(0) {
return fmt.Errorf("InvokeInterval %v must be above 0s", ssc.InvokeInterval)
}
if _, err := os.Stat(ssc.ProcPath); err != nil {
return fmt.Errorf("ProcPath %v check failed: %s", err)
}
if ssc.DiskConfig.LsblkTimeout <= time.Duration(0) {
return fmt.Errorf("LsblkTimeout %v must be above 0s", ssc.DiskConfig.LsblkTimeout)
}
Expand Down
4 changes: 1 addition & 3 deletions pkg/util/metrics/system/cmdline_args.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ import (
"strings"
)

var cmdlineFilePath = "/proc/cmdline"

type CmdlineArg struct {
Key string `json:"key"`
Value string `json:"value"`
Expand Down Expand Up @@ -52,7 +50,7 @@ func splitAfterSpace(inputChar rune) bool {
}

// CmdlineArgs returns all the kernel cmdline. It is read from cat /proc/cmdline.
func CmdlineArgs() ([]CmdlineArg, error) {
func CmdlineArgs(cmdlineFilePath string) ([]CmdlineArg, error) {
lines, err := ReadFileIntoLines(cmdlineFilePath)
if err != nil {
return nil, fmt.Errorf("error reading the file %s, %v", cmdlineFilePath, err)
Expand Down
10 changes: 2 additions & 8 deletions pkg/util/metrics/system/cmdline_args_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,9 @@ func TestCmdlineStats(t *testing.T) {
}
for _, test := range testcases {
t.Run(test.name, func(t *testing.T) {
originalCmdlineFilePath := cmdlineFilePath
defer func() {
cmdlineFilePath = originalCmdlineFilePath
}()

cmdlineFilePath = test.fakeCmdlineFilePath
cmdlineArgs, err := CmdlineArgs()
cmdlineArgs, err := CmdlineArgs(test.fakeCmdlineFilePath)
if err != nil {
t.Errorf("Unexpected error retrieving cmdlineArgs: %v\nCmdlineArgsFilePath: %s\n", err, cmdlineFilePath)
t.Errorf("Unexpected error retrieving cmdlineArgs: %v\nCmdlineArgsFilePath: %s\n", err, test.fakeCmdlineFilePath)
}
for _, expectedCmdlineArg := range test.expectedCmdlineArgs {
assert.Contains(t, cmdlineArgs, expectedCmdlineArg, "Failed to find cmdlineArgs: %v\n", expectedCmdlineArg)
Expand Down
4 changes: 1 addition & 3 deletions pkg/util/metrics/system/module_stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ import (
"strings"
)

var modulesFilePath = "/proc/modules"

type Module struct {
ModuleName string `json:"moduleName"`
Instances uint64 `json:"instances"`
Expand All @@ -37,7 +35,7 @@ func (d Module) String() string {

// Module returns all the kernel modules and their
// usage. It is read from cat /proc/modules.
func Modules() ([]Module, error) {
func Modules(modulesFilePath string) ([]Module, error) {
lines, err := ReadFileIntoLines(modulesFilePath)
if err != nil {
return nil, fmt.Errorf("error reading the contents of %s: %s", modulesFilePath, err)
Expand Down
10 changes: 2 additions & 8 deletions pkg/util/metrics/system/module_stats_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,9 @@ func TestModules(t *testing.T) {
}
for _, test := range testcases {
t.Run(test.name, func(t *testing.T) {
originalModuleFilePath := modulesFilePath
defer func() {
modulesFilePath = originalModuleFilePath
}()

modulesFilePath = test.fakeModuleFilePath
modules, err := Modules()
modules, err := Modules(test.fakeModuleFilePath)
if err != nil {
t.Errorf("Unexpected error retrieving modules: %v\nModulesFilePath: %s\n", err, modulesFilePath)
t.Errorf("Unexpected error retrieving modules: %v\nModulesFilePath: %s\n", err, test.fakeModuleFilePath)
}
assert.Equal(t, modules, test.expectedModules, "unpected modules retrieved: %v, expected: %v", modules, test.expectedModules)
})
Expand Down

0 comments on commit 6e7a107

Please sign in to comment.