From 0a86b24b08431c597519e19937b07162247035e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20R=C3=BCger?= Date: Thu, 8 Aug 2024 18:57:22 +0200 Subject: [PATCH] chore: Memory align structs pkg/metric_generator/generator.go:32:22: 16 bytes saved: struct with 96 pointer bytes could be 80 pkg/metrics_store/metrics_store.go:31:19: 40 bytes saved: struct with 64 pointer bytes could be 24 pkg/options/options.go:42:14: 24 bytes saved: struct of size 384 could be 360 internal/store/builder.go:67:14: 8 bytes saved: struct of size 200 could be 192 internal/store/pod.go:1351:16: 8 bytes saved: struct with 16 pointer bytes could be 8 internal/store/pod.go:1477:20: 8 bytes saved: struct with 16 pointer bytes could be 8 internal/store/testutils.go:32:30: 16 bytes saved: struct with 136 pointer bytes could be 120 pkg/metricshandler/metrics_handler.go:46:21: 8 bytes saved: struct of size 104 could be 96 internal/discovery/types.go:39:19: 32 bytes saved: struct with 88 pointer bytes could be 56 pkg/customresourcestate/config.go:51:15: 16 bytes saved: struct with 112 pointer bytes could be 96 pkg/customresourcestate/config.go:134:16: 8 bytes saved: struct with 88 pointer bytes could be 80 pkg/customresourcestate/config.go:150:13: 8 bytes saved: struct with 40 pointer bytes could be 32 pkg/customresourcestate/config_metrics_types.go:29:18: 8 bytes saved: struct with 64 pointer bytes could be 56 pkg/customresourcestate/config_metrics_types.go:42:17: 8 bytes saved: struct with 40 pointer bytes could be 32 pkg/customresourcestate/registry_factory.go:125:21: 8 bytes saved: struct with 40 pointer bytes could be 32 pkg/customresourcestate/registry_factory.go:212:20: 16 bytes saved: struct with 88 pointer bytes could be 72 pkg/customresourcestate/registry_factory.go:377:23: 8 bytes saved: struct with 104 pointer bytes could be 96 pkg/customresourcestate/registry_factory.go:497:21: 8 bytes saved: struct with 64 pointer bytes could be 56 pkg/customresourcestate/registry_factory.go:549:13: 8 bytes saved: struct with 24 pointer bytes could be 16 --- internal/discovery/types.go | 12 ++-- internal/store/builder.go | 18 ++--- internal/store/pod.go | 20 +++--- internal/store/testutils.go | 4 +- pkg/customresourcestate/config.go | 25 +++---- .../config_metrics_types.go | 8 +-- pkg/customresourcestate/registry_factory.go | 12 ++-- pkg/metric_generator/generator.go | 4 +- pkg/metrics_store/metrics_store.go | 11 +-- pkg/metricshandler/metrics_handler.go | 16 ++--- pkg/options/options.go | 70 ++++++++++--------- 11 files changed, 102 insertions(+), 98 deletions(-) diff --git a/internal/discovery/types.go b/internal/discovery/types.go index 7de4a6ca4a..5b95778a8e 100644 --- a/internal/discovery/types.go +++ b/internal/discovery/types.go @@ -37,18 +37,18 @@ type kindPlural struct { // CRDiscoverer provides a cache of the collected GVKs, along with helper utilities. type CRDiscoverer struct { - // m is a mutex to protect the cache. - m sync.RWMutex - // Map is a cache of the collected GVKs. - Map map[string]map[string][]kindPlural - // ShouldUpdate is a flag that indicates whether the cache was updated. - WasUpdated bool // CRDsAddEventsCounter tracks the number of times that the CRD informer triggered the "add" event. CRDsAddEventsCounter prometheus.Counter // CRDsDeleteEventsCounter tracks the number of times that the CRD informer triggered the "remove" event. CRDsDeleteEventsCounter prometheus.Counter // CRDsCacheCountGauge tracks the net amount of CRDs affecting the cache at this point. CRDsCacheCountGauge prometheus.Gauge + // Map is a cache of the collected GVKs. + Map map[string]map[string][]kindPlural + // m is a mutex to protect the cache. + m sync.RWMutex + // ShouldUpdate is a flag that indicates whether the cache was updated. + WasUpdated bool } // SafeRead executes the given function while holding a read lock. diff --git a/internal/store/builder.go b/internal/store/builder.go index db4e06baa9..f7941794e4 100644 --- a/internal/store/builder.go +++ b/internal/store/builder.go @@ -65,24 +65,24 @@ var _ ksmtypes.BuilderInterface = &Builder{} // Builder helps to build store. It follows the builder pattern // (https://en.wikipedia.org/wiki/Builder_pattern). type Builder struct { - kubeClient clientset.Interface - customResourceClients map[string]interface{} - namespaces options.NamespaceList - // namespaceFilter is inside fieldSelectorFilter - fieldSelectorFilter string + kubeClient clientset.Interface ctx context.Context - enabledResources []string familyGeneratorFilter generator.FamilyGeneratorFilter + customResourceClients map[string]interface{} listWatchMetrics *watch.ListWatchMetrics shardingMetrics *sharding.Metrics - shard int32 - totalShards int buildStoresFunc ksmtypes.BuildStoresFunc buildCustomResourceStoresFunc ksmtypes.BuildCustomResourceStoresFunc allowAnnotationsList map[string][]string allowLabelsList map[string][]string - useAPIServerCache bool utilOptions *options.Options + // namespaceFilter is inside fieldSelectorFilter + fieldSelectorFilter string + namespaces options.NamespaceList + enabledResources []string + totalShards int + shard int32 + useAPIServerCache bool } // NewBuilder returns a new builder. diff --git a/internal/store/pod.go b/internal/store/pod.go index 82da1a43b3..8c39017283 100644 --- a/internal/store/pod.go +++ b/internal/store/pod.go @@ -1349,14 +1349,14 @@ func createPodStatusPhaseFamilyGenerator() generator.FamilyGenerator { } phases := []struct { - v bool n string + v bool }{ - {phase == v1.PodPending, string(v1.PodPending)}, - {phase == v1.PodSucceeded, string(v1.PodSucceeded)}, - {phase == v1.PodFailed, string(v1.PodFailed)}, - {phase == v1.PodUnknown, string(v1.PodUnknown)}, - {phase == v1.PodRunning, string(v1.PodRunning)}, + {string(v1.PodPending), phase == v1.PodPending}, + {string(v1.PodSucceeded), phase == v1.PodSucceeded}, + {string(v1.PodFailed), phase == v1.PodFailed}, + {string(v1.PodUnknown), phase == v1.PodUnknown}, + {string(v1.PodRunning), phase == v1.PodRunning}, } ms := make([]*metric.Metric, len(phases)) @@ -1475,12 +1475,12 @@ func createPodStatusQosClassFamilyGenerator() generator.FamilyGenerator { } qosClasses := []struct { - v bool n string + v bool }{ - {class == v1.PodQOSBestEffort, string(v1.PodQOSBestEffort)}, - {class == v1.PodQOSBurstable, string(v1.PodQOSBurstable)}, - {class == v1.PodQOSGuaranteed, string(v1.PodQOSGuaranteed)}, + {string(v1.PodQOSBestEffort), class == v1.PodQOSBestEffort}, + {string(v1.PodQOSBurstable), class == v1.PodQOSBurstable}, + {string(v1.PodQOSGuaranteed), class == v1.PodQOSGuaranteed}, } ms := make([]*metric.Metric, len(qosClasses)) diff --git a/internal/store/testutils.go b/internal/store/testutils.go index 8de6c52ae2..2c52838fff 100644 --- a/internal/store/testutils.go +++ b/internal/store/testutils.go @@ -31,12 +31,12 @@ import ( type generateMetricsTestCase struct { Obj interface{} + Func func(interface{}) []metric.FamilyInterface + Want string MetricNames []string AllowAnnotationsList []string AllowLabelsList []string - Want string Headers []string - Func func(interface{}) []metric.FamilyInterface } func (testCase *generateMetricsTestCase) run() error { diff --git a/pkg/customresourcestate/config.go b/pkg/customresourcestate/config.go index 873591372f..f9beb2083e 100644 --- a/pkg/customresourcestate/config.go +++ b/pkg/customresourcestate/config.go @@ -49,6 +49,10 @@ type MetricsSpec struct { // Resource configures a custom resource for metric generation. type Resource struct { + + // Labels are added to all metrics. If the same key is used in a metric, the value from the metric will overwrite the value here. + Labels `yaml:",inline" json:",inline"` + // MetricNamePrefix defines a prefix for all metrics of the resource. // If set to "", no prefix will be added. // Example: If set to "foo", MetricNamePrefix will be "foo_". @@ -57,16 +61,13 @@ type Resource struct { // GroupVersionKind of the custom resource to be monitored. GroupVersionKind GroupVersionKind `yaml:"groupVersionKind" json:"groupVersionKind"` - // Labels are added to all metrics. If the same key is used in a metric, the value from the metric will overwrite the value here. - Labels `yaml:",inline" json:",inline"` + // ResourcePlural sets the plural name of the resource. Defaults to the plural version of the Kind according to flect.Pluralize. + ResourcePlural string `yaml:"resourcePlural" json:"resourcePlural"` // Metrics are the custom resource fields to be collected. Metrics []Generator `yaml:"metrics" json:"metrics"` // ErrorLogV defines the verbosity threshold for errors logged for this resource. ErrorLogV klog.Level `yaml:"errorLogV" json:"errorLogV"` - - // ResourcePlural sets the plural name of the resource. Defaults to the plural version of the Kind according to flect.Pluralize. - ResourcePlural string `yaml:"resourcePlural" json:"resourcePlural"` } // GetMetricNamePrefix returns the prefix to use for metrics. @@ -132,15 +133,15 @@ func (l Labels) Merge(other Labels) Labels { // Generator describes a unique metric name. type Generator struct { - // Name of the metric. Subject to prefixing based on the configuration of the Resource. - Name string `yaml:"name" json:"name"` - // Help text for the metric. - Help string `yaml:"help" json:"help"` // Each targets a value or values from the resource. Each Metric `yaml:"each" json:"each"` // Labels are added to all metrics. Labels from Each will overwrite these if using the same key. Labels `yaml:",inline" json:",inline"` // json will inline because it is already tagged + // Name of the metric. Subject to prefixing based on the configuration of the Resource. + Name string `yaml:"name" json:"name"` + // Help text for the metric. + Help string `yaml:"help" json:"help"` // ErrorLogV defines the verbosity threshold for errors logged for this metric. Must be non-zero to override the resource setting. ErrorLogV klog.Level `yaml:"errorLogV" json:"errorLogV"` } @@ -148,9 +149,6 @@ type Generator struct { // Metric defines a metric to expose. // +union type Metric struct { - // Type defines the type of the metric. - // +unionDiscriminator - Type metric.Type `yaml:"type" json:"type"` // Gauge defines a gauge metric. // +optional @@ -161,6 +159,9 @@ type Metric struct { // Info defines an info metric. // +optional Info *MetricInfo `yaml:"info" json:"info"` + // Type defines the type of the metric. + // +unionDiscriminator + Type metric.Type `yaml:"type" json:"type"` } // ConfigDecoder is for use with FromConfig. diff --git a/pkg/customresourcestate/config_metrics_types.go b/pkg/customresourcestate/config_metrics_types.go index 25d63bfb69..5b06e46421 100644 --- a/pkg/customresourcestate/config_metrics_types.go +++ b/pkg/customresourcestate/config_metrics_types.go @@ -27,12 +27,12 @@ type MetricMeta struct { // MetricGauge targets a Path that may be a single value, array, or object. Arrays and objects will generate a metric per element. // Ref: https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#gauge type MetricGauge struct { - MetricMeta `yaml:",inline" json:",inline"` + // LabelFromKey adds a label with the given name if Path is an object. The label value will be the object key. + LabelFromKey string `yaml:"labelFromKey" json:"labelFromKey"` + MetricMeta `yaml:",inline" json:",inline"` // ValueFrom is the path to a numeric field under Path that will be the metric value. ValueFrom []string `yaml:"valueFrom" json:"valueFrom"` - // LabelFromKey adds a label with the given name if Path is an object. The label value will be the object key. - LabelFromKey string `yaml:"labelFromKey" json:"labelFromKey"` // NilIsZero indicates that if a value is nil it will be treated as zero value. NilIsZero bool `yaml:"nilIsZero" json:"nilIsZero"` } @@ -40,9 +40,9 @@ type MetricGauge struct { // MetricInfo is a metric which is used to expose textual information. // Ref: https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#info type MetricInfo struct { - MetricMeta `yaml:",inline" json:",inline"` // LabelFromKey adds a label with the given name if Path is an object. The label value will be the object key. LabelFromKey string `yaml:"labelFromKey" json:"labelFromKey"` + MetricMeta `yaml:",inline" json:",inline"` } // MetricStateSet is a metric which represent a series of related boolean values, also called a bitset. diff --git a/pkg/customresourcestate/registry_factory.go b/pkg/customresourcestate/registry_factory.go index c59f5aeabe..e4413d4dc2 100644 --- a/pkg/customresourcestate/registry_factory.go +++ b/pkg/customresourcestate/registry_factory.go @@ -124,8 +124,8 @@ type compiledEach compiledMetric type compiledCommon struct { labelFromPath map[string]valuePath - path valuePath t metric.Type + path valuePath } func (c compiledCommon) Path() valuePath { @@ -211,9 +211,9 @@ func newCompiledMetric(m Metric) (compiledMetric, error) { type compiledGauge struct { compiledCommon + labelFromKey string ValueFrom valuePath NilIsZero bool - labelFromKey string } func (c *compiledGauge) Values(v interface{}) (result []eachValue, errs []error) { @@ -376,9 +376,9 @@ func (c *compiledInfo) values(v interface{}) (result []eachValue, err []error) { type compiledStateSet struct { compiledCommon + LabelName string ValueFrom valuePath List []string - LabelName string } func (c *compiledStateSet) Values(v interface{}) (result []eachValue, errs []error) { @@ -495,11 +495,11 @@ func (e eachValue) ToMetric() *metric.Metric { } type compiledFamily struct { - Name string - Help string Each compiledEach Labels map[string]string LabelFromPath map[string]valuePath + Name string + Help string ErrorLogV klog.Level } @@ -547,8 +547,8 @@ func addPathLabels(obj interface{}, labels map[string]valuePath, result map[stri } type pathOp struct { - part string op func(interface{}) interface{} + part string } type valuePath []pathOp diff --git a/pkg/metric_generator/generator.go b/pkg/metric_generator/generator.go index 2a2e30221f..5601ea5252 100644 --- a/pkg/metric_generator/generator.go +++ b/pkg/metric_generator/generator.go @@ -30,13 +30,13 @@ import ( // DeprecatedVersion is defined only if the metric for which this options applies is, // in fact, deprecated. type FamilyGenerator struct { + GenerateFunc func(obj interface{}) *metric.Family Name string Help string Type metric.Type - OptIn bool DeprecatedVersion string StabilityLevel basemetrics.StabilityLevel - GenerateFunc func(obj interface{}) *metric.Family + OptIn bool } // NewFamilyGeneratorWithStability creates new FamilyGenerator instances with metric diff --git a/pkg/metrics_store/metrics_store.go b/pkg/metrics_store/metrics_store.go index 25b4bb4950..0339101b5b 100644 --- a/pkg/metrics_store/metrics_store.go +++ b/pkg/metrics_store/metrics_store.go @@ -29,21 +29,22 @@ import ( // interface. Instead of storing entire Kubernetes objects, it stores metrics // generated based on those objects. type MetricsStore struct { - // Protects metrics - mutex sync.RWMutex // metrics is a map indexed by Kubernetes object id, containing a slice of // metric families, containing a slice of metrics. We need to keep metrics // grouped by metric families in order to zip families with their help text in // MetricsStore.WriteAll(). metrics map[types.UID][][]byte + + // generateMetricsFunc generates metrics based on a given Kubernetes object + // and returns them grouped by metric family. + generateMetricsFunc func(interface{}) []metric.FamilyInterface // headers contains the header (TYPE and HELP) of each metric family. It is // later on zipped with with their corresponding metric families in // MetricStore.WriteAll(). headers []string - // generateMetricsFunc generates metrics based on a given Kubernetes object - // and returns them grouped by metric family. - generateMetricsFunc func(interface{}) []metric.FamilyInterface + // Protects metrics + mutex sync.RWMutex } // NewMetricsStore returns a new MetricsStore diff --git a/pkg/metricshandler/metrics_handler.go b/pkg/metricshandler/metrics_handler.go index 62543785b0..e944033c12 100644 --- a/pkg/metricshandler/metrics_handler.go +++ b/pkg/metricshandler/metrics_handler.go @@ -44,18 +44,18 @@ import ( // MetricsHandler is a http.Handler that exposes the main kube-state-metrics // /metrics endpoint. It allows concurrent reconfiguration at runtime. type MetricsHandler struct { - opts *options.Options - kubeClient kubernetes.Interface - storeBuilder ksmtypes.BuilderInterface - enableGZIPEncoding bool + kubeClient kubernetes.Interface + storeBuilder ksmtypes.BuilderInterface + opts *options.Options cancel func() // mtx protects metricsWriters, curShard, and curTotalShards - mtx *sync.RWMutex - metricsWriters metricsstore.MetricsWriterList - curShard int32 - curTotalShards int + mtx *sync.RWMutex + metricsWriters metricsstore.MetricsWriterList + curTotalShards int + curShard int32 + enableGZIPEncoding bool } // New creates and returns a new MetricsHandler with the given options. diff --git a/pkg/options/options.go b/pkg/options/options.go index d10a12cce2..2b601bb439 100644 --- a/pkg/options/options.go +++ b/pkg/options/options.go @@ -40,43 +40,45 @@ var ( // Options are the configurable parameters for kube-state-metrics. type Options struct { - AnnotationsAllowList LabelsAllowList `yaml:"annotations_allow_list"` - Apiserver string `yaml:"apiserver"` - AutoGoMemlimit bool `yaml:"auto-gomemlimit"` - AutoGoMemlimitRatio float64 `yaml:"auto-gomemlimit-ratio"` - CustomResourceConfig string `yaml:"custom_resource_config"` - CustomResourceConfigFile string `yaml:"custom_resource_config_file"` - CustomResourcesOnly bool `yaml:"custom_resources_only"` - EnableGZIPEncoding bool `yaml:"enable_gzip_encoding"` - Help bool `yaml:"help"` - Host string `yaml:"host"` - Kubeconfig string `yaml:"kubeconfig"` - LabelsAllowList LabelsAllowList `yaml:"labels_allow_list"` - MetricAllowlist MetricSet `yaml:"metric_allowlist"` - MetricDenylist MetricSet `yaml:"metric_denylist"` - MetricOptInList MetricSet `yaml:"metric_opt_in_list"` - Namespace string `yaml:"namespace"` - Namespaces NamespaceList `yaml:"namespaces"` - NamespacesDenylist NamespaceList `yaml:"namespaces_denylist"` - Node NodeType `yaml:"node"` - TrackUnscheduledPods bool `yaml:"track_unscheduled_pods"` - Pod string `yaml:"pod"` - Port int `yaml:"port"` - Resources ResourceSet `yaml:"resources"` - Shard int32 `yaml:"shard"` - TLSConfig string `yaml:"tls_config"` - TelemetryHost string `yaml:"telemetry_host"` - TelemetryPort int `yaml:"telemetry_port"` - TotalShards int `yaml:"total_shards"` - UseAPIServerCache bool `yaml:"use_api_server_cache"` - ServerReadTimeout time.Duration `yaml:"server_read_timeout"` - ServerWriteTimeout time.Duration `yaml:"server_write_timeout"` - ServerIdleTimeout time.Duration `yaml:"server_idle_timeout"` - ServerReadHeaderTimeout time.Duration `yaml:"server_read_header_timeout"` + AnnotationsAllowList LabelsAllowList `yaml:"annotations_allow_list"` + LabelsAllowList LabelsAllowList `yaml:"labels_allow_list"` + MetricAllowlist MetricSet `yaml:"metric_allowlist"` + MetricDenylist MetricSet `yaml:"metric_denylist"` + MetricOptInList MetricSet `yaml:"metric_opt_in_list"` + Resources ResourceSet `yaml:"resources"` + + cmd *cobra.Command + Apiserver string `yaml:"apiserver"` + CustomResourceConfig string `yaml:"custom_resource_config"` + CustomResourceConfigFile string `yaml:"custom_resource_config_file"` + Host string `yaml:"host"` + Kubeconfig string `yaml:"kubeconfig"` + Namespace string `yaml:"namespace"` + Node NodeType `yaml:"node"` + Pod string `yaml:"pod"` + TLSConfig string `yaml:"tls_config"` + TelemetryHost string `yaml:"telemetry_host"` Config string - cmd *cobra.Command + Namespaces NamespaceList `yaml:"namespaces"` + NamespacesDenylist NamespaceList `yaml:"namespaces_denylist"` + AutoGoMemlimitRatio float64 `yaml:"auto-gomemlimit-ratio"` + Port int `yaml:"port"` + TelemetryPort int `yaml:"telemetry_port"` + TotalShards int `yaml:"total_shards"` + ServerReadTimeout time.Duration `yaml:"server_read_timeout"` + ServerWriteTimeout time.Duration `yaml:"server_write_timeout"` + ServerIdleTimeout time.Duration `yaml:"server_idle_timeout"` + ServerReadHeaderTimeout time.Duration `yaml:"server_read_header_timeout"` + + Shard int32 `yaml:"shard"` + AutoGoMemlimit bool `yaml:"auto-gomemlimit"` + CustomResourcesOnly bool `yaml:"custom_resources_only"` + EnableGZIPEncoding bool `yaml:"enable_gzip_encoding"` + Help bool `yaml:"help"` + TrackUnscheduledPods bool `yaml:"track_unscheduled_pods"` + UseAPIServerCache bool `yaml:"use_api_server_cache"` } // GetConfigFile is the getter for --config value.