Skip to content

Commit

Permalink
api: added disabledCollectors config option
Browse files Browse the repository at this point in the history
The validation of config options will be done by the operator's
validation webhook.
Validation tests are going to be part of the operator repo.
The MetricsExporterConfigSpec shall be inlined in
the StorageOSCluster.Spec.Metrics.
Operator will be responsible for ConfigMap's creation and patching based
on the StorageOSCluster.Spec.Metrics values.

Signed-off-by: Michal Minář <[email protected]>
  • Loading branch information
Michal Minář committed Jun 27, 2022
1 parent 8ed2fd3 commit bf5d083
Show file tree
Hide file tree
Showing 10 changed files with 233 additions and 20 deletions.
23 changes: 23 additions & 0 deletions api/config.storageos.com/v1/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
Copyright 2022 Ondat.
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
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1

const (
// MetricsExporterConfigFileName is a mandatory key in the data field of the
// ConfigMap/storage-metrics-exporter. The associated value must be a valid MetricsExporterConfig
// serialized as YAML.
MetricsExporterConfigFileName = "config.yaml"
)
26 changes: 26 additions & 0 deletions api/config.storageos.com/v1/default.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
Copyright 2022 Ondat.
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
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1

func (c *MetricsExporterConfig) Default() *MetricsExporterConfig {
if c.LogLevel == "" {
c.LogLevel = "info"
}
if c.Timeout == 0 {
c.Timeout = 10
}
return c
}
21 changes: 20 additions & 1 deletion api/config.storageos.com/v1/metricsexporterconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ type MetricsExporterConfig struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

MetricsExporterConfigSpec `json:",inline"`
}

// MetricsExporterConfigSpec represents the configuration options for the metrics-exporter. These fields shall
// be inlined in the StorageOSCluster.Spec.Metrics.
type MetricsExporterConfigSpec struct {
// Verbosity of log messages. Accepts go.uber.org/zap log levels.
// +kubebuilder:default:info
// +kubebuilder:validation:Enum=debug;info;warn;error;dpanic;panic;fatal
Expand All @@ -36,9 +42,22 @@ type MetricsExporterConfig struct {
// Timeout in seconds to serve metrics.
// +kubebuilder:default:10
// +kubebuilder:validation:Minimum=1
Timeout int `json:"timeout"`
Timeout int `json:"timeout,omitempty"`

// DisabledCollectors is a list of collectors that shall be disabled. By default, all are enabled.
DisabledCollectors []MetricsExporterCollector `json:"disabledCollectors,omitempty"`
}

// MetricsExporterCollector is the name of a metrics collector in the metrics-exporter.
// +kubebuilder:validation:Enum=diskstats;filesystem
type MetricsExporterCollector string

// All known metrics-exporter collectors are listed here.
const (
MetricsExporterCollectorDiskStats MetricsExporterCollector = "diskstats"
MetricsExporterCollectorFileSystem MetricsExporterCollector = "filesystem"
)

func init() {
SchemeBuilder.Register(&MetricsExporterConfig{})
}
21 changes: 21 additions & 0 deletions api/config.storageos.com/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"github.com/google/uuid"
"github.com/prometheus/client_golang/prometheus"
"go.uber.org/zap"

configondatv1 "github.com/ondat/metrics-exporter/api/config.storageos.com/v1"
)

type Collector interface {
Expand Down Expand Up @@ -77,3 +79,33 @@ func execute(log *zap.SugaredLogger, c Collector, ch chan<- prometheus.Metric, o
}
ch <- prometheus.MustNewConstMetric(scrapeSuccessMetric.desc, scrapeSuccessMetric.valueType, success, c.Name())
}

func GetEnabledMetricsCollectors(
log *zap.SugaredLogger,
disabled []configondatv1.MetricsExporterCollector,
) []Collector {
var metricsCollectors []Collector
for name, collectorFactory := range map[configondatv1.MetricsExporterCollector](func() Collector){
configondatv1.MetricsExporterCollectorDiskStats: func() Collector { return NewDiskStatsCollector() },
configondatv1.MetricsExporterCollectorFileSystem: func() Collector { return NewFileSystemCollector() },
} {
if IsCollectorDisabled(disabled, name) {
log.Infof("disabling %s collector", name)
continue
}
metricsCollectors = append(metricsCollectors, collectorFactory())
}
return metricsCollectors
}

func IsCollectorDisabled(
disabled []configondatv1.MetricsExporterCollector,
collector configondatv1.MetricsExporterCollector,
) bool {
for _, c := range disabled {
if c == collector {
return true
}
}
return false
}
90 changes: 90 additions & 0 deletions collector_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package main

import (
"testing"

"github.com/stretchr/testify/require"
"go.uber.org/zap"

configondatv1 "github.com/ondat/metrics-exporter/api/config.storageos.com/v1"
)

func TestGetEnabledMetricsCollectors(t *testing.T) {
tests := []struct {
name string
disable []configondatv1.MetricsExporterCollector
expectedEnabled []string
}{
{
name: "all enabled",
disable: nil,
expectedEnabled: []string{
"diskstats",
"filesystem",
},
},

{
name: "disable filesystem",
disable: []configondatv1.MetricsExporterCollector{configondatv1.MetricsExporterCollectorFileSystem},
expectedEnabled: []string{
"diskstats",
},
},

{
name: "disable diskstats",
disable: []configondatv1.MetricsExporterCollector{configondatv1.MetricsExporterCollectorDiskStats},
expectedEnabled: []string{
"filesystem",
},
},

{
name: "disable both",
disable: []configondatv1.MetricsExporterCollector{
configondatv1.MetricsExporterCollectorFileSystem,
configondatv1.MetricsExporterCollectorDiskStats,
},
expectedEnabled: []string{},
},

{
name: "disable both - reversed",
disable: []configondatv1.MetricsExporterCollector{
configondatv1.MetricsExporterCollectorDiskStats,
configondatv1.MetricsExporterCollectorFileSystem,
},
expectedEnabled: []string{},
},

{
name: "ignore bad value",
disable: []configondatv1.MetricsExporterCollector{
configondatv1.MetricsExporterCollector("bad"),
configondatv1.MetricsExporterCollectorFileSystem,
},
expectedEnabled: []string{
"diskstats",
},
},
}

for _, tt := range tests {
var tt = tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()

loggerConfig := zap.NewProductionConfig()
logger, _ := loggerConfig.Build()
log := logger.Sugar()

collectors := GetEnabledMetricsCollectors(log, tt.disable)
names := make([]string, 0, len(collectors))
for _, c := range collectors {
names = append(names, c.Name())
}
require.ElementsMatch(t, tt.expectedEnabled, names)
})
}
}
23 changes: 10 additions & 13 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,10 @@ import (
"log"
"os"

configondatv1 "github.com/ondat/metrics-exporter/api/config.storageos.com/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer"
)

var (
configDefaults = configondatv1.MetricsExporterConfig{
LogLevel: "info",
Timeout: 10,
}
configondatv1 "github.com/ondat/metrics-exporter/api/config.storageos.com/v1"
)

func readConfigFile(path string) (*configondatv1.MetricsExporterConfig, error) {
Expand All @@ -42,25 +36,28 @@ func readConfigFile(path string) (*configondatv1.MetricsExporterConfig, error) {

codecs := serializer.NewCodecFactory(scheme)

cfg := *configDefaults.DeepCopy()
if err = runtime.DecodeInto(codecs.UniversalDecoder(), content, &cfg); err != nil {
cfg := (&configondatv1.MetricsExporterConfig{}).Default()
if err = runtime.DecodeInto(codecs.UniversalDecoder(), content, cfg); err != nil {
return nil, fmt.Errorf("could not decode file into runtime.Object: %v", err)
}
return &cfg, nil

return cfg, nil
}

func getConfigOrDie() (path string, cfg configondatv1.MetricsExporterConfig) {
var configFile string
var logLevelFlag string
var timeoutFlag int

defaults := (&configondatv1.MetricsExporterConfig{}).Default()

flag.StringVar(&configFile, "config", "",
"The exporter will load its initial configuration from this file. "+
"Omit this flag to use the default configuration values. "+
"Command-line flags override configuration from this file.")
flag.StringVar(&logLevelFlag, "log-level", configDefaults.LogLevel,
flag.StringVar(&logLevelFlag, "log-level", defaults.LogLevel,
"Verbosity of log messages. Accepts go.uber.org/zap log levels.")
flag.IntVar(&timeoutFlag, "timeout", configDefaults.Timeout, "Timeout in seconds to serve metrics.")
flag.IntVar(&timeoutFlag, "timeout", defaults.Timeout, "Timeout in seconds to serve metrics.")
flag.Parse()

if len(configFile) > 0 {
Expand All @@ -71,7 +68,7 @@ func getConfigOrDie() (path string, cfg configondatv1.MetricsExporterConfig) {
}
cfg = *parsedCfg
} else {
cfg = *configDefaults.DeepCopy()
cfg = *defaults
}

// override defaults/configmap with the supplied flag values
Expand Down
4 changes: 3 additions & 1 deletion diskstats_collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import (

"github.com/prometheus/client_golang/prometheus"
"go.uber.org/zap"

configondatv1 "github.com/ondat/metrics-exporter/api/config.storageos.com/v1"
)

const (
// SECOND_IN_MILLISECONDS defines the number of seconds on a milliseconds. Used
// to transform metrics that express a duration in milliseconds.
SECOND_IN_MILLISECONDS = 1.0 / 1000.0
DISKSTATS_COLLECTOR_NAME = "diskstats"
DISKSTATS_COLLECTOR_NAME = string(configondatv1.MetricsExporterCollectorDiskStats)
)

// DiskStatsCollector implements the prometheus Collector interface
Expand Down
4 changes: 3 additions & 1 deletion filesystem_collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ import (
"github.com/prometheus/client_golang/prometheus"
"go.uber.org/zap"
"golang.org/x/sys/unix"

configondatv1 "github.com/ondat/metrics-exporter/api/config.storageos.com/v1"
)

const FILE_SYSTEM_COLLECTOR_NAME = "filesystem"
const FILE_SYSTEM_COLLECTOR_NAME = string(configondatv1.MetricsExporterCollectorFileSystem)

var stuckMounts = make(map[string]struct{})
var stuckMountsMtx = &sync.Mutex{}
Expand Down
9 changes: 5 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,14 @@ import (
"os"
"time"

configondatv1 "github.com/ondat/metrics-exporter/api/config.storageos.com/v1"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"

configondatv1 "github.com/ondat/metrics-exporter/api/config.storageos.com/v1"
)

const (
Expand Down Expand Up @@ -72,9 +73,9 @@ func main() {
}
log.Debugf("Serve metrics timeout set to %d seconds", cfg.Timeout)

metricsCollectors := []Collector{
NewDiskStatsCollector(),
NewFileSystemCollector(),
metricsCollectors := GetEnabledMetricsCollectors(log, cfg.DisabledCollectors)
if len(metricsCollectors) == 0 {
log.Fatal("there is nothing to do with all metrics collectors disabled")
}

prometheusRegistry := prometheus.NewRegistry()
Expand Down

0 comments on commit bf5d083

Please sign in to comment.