Skip to content

Commit

Permalink
Merge pull request #44 from ondat/ctrl-216
Browse files Browse the repository at this point in the history
Ctrl-216 - Allow to disable metrics collectors
  • Loading branch information
Michal Minář authored Jun 27, 2022
2 parents 152dc1f + bf5d083 commit 6056b1c
Show file tree
Hide file tree
Showing 14 changed files with 237 additions and 24 deletions.
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@
!go.mod
!go.sum
!index.html
# ignore local GOPATH=$(pwd)/.go/
.go/
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
FROM golang:1.17.3 as builder

WORKDIR /workspace
COPY . .
COPY go.mod go.sum ./

# cache deps before building and copying source so that we don't need to re-download as much
# and so that source changes don't invalidate our downloaded layer
RUN go mod download
COPY . .

# Build
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o metrics-exporter .
Expand Down
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
Loading

0 comments on commit 6056b1c

Please sign in to comment.